Whamcloud - gitweb
LU-10070 lod: SEL cleanup 14/35414/4
authorVitaly Fertman <c17818@cray.com>
Wed, 3 Jul 2019 17:10:53 +0000 (20:10 +0300)
committerOleg Drokin <green@whamcloud.com>
Sat, 20 Jul 2019 18:38:58 +0000 (18:38 +0000)
some cleanups
- dt_statfs with an extra paremeter to be dt_statfs_info;
- lod_statfs_and_check does not need an extra parameter and
to be static again;
- move asserts to a better place;
- test component-add with wrong paremeters;
- print out the layout sanity errors wherever needed;
- make an array of layout_sanity errors;
- an HSM sanity test is added;

and one defect:
- the last component cannot be 0-lenght;

Signed-off-by: Vitaly Fertman <c17818@cray.com>
Change-Id: If832579ce27cb6ab87d36a594c04363deaea8711
Reviewed-on: https://review.whamcloud.com/35414
Tested-by: jenkins <devops@whamcloud.com>
Tested-by: Maloo <maloo@whamcloud.com>
Reviewed-by: Alexey Lyashkov <c17817@cray.com>
Reviewed-by: Patrick Farrell <pfarrell@whamcloud.com>
Reviewed-by: Oleg Drokin <green@whamcloud.com>
15 files changed:
lustre/include/dt_object.h
lustre/lod/lod_dev.c
lustre/lod/lod_internal.h
lustre/lod/lod_object.c
lustre/lod/lod_qos.c
lustre/lod/lproc_lod.c
lustre/mdt/mdt_handler.c
lustre/obdclass/dt_object.c
lustre/obdclass/llog_cat.c
lustre/obdclass/obd_mount_server.c
lustre/ofd/ofd_obd.c
lustre/target/tgt_grant.c
lustre/tests/sanity-hsm.sh
lustre/tests/sanity-pfl.sh
lustre/utils/liblustreapi_layout.c

index 5ff7815..950c372 100644 (file)
@@ -2514,9 +2514,10 @@ static inline int dt_fiemap_get(const struct lu_env *env, struct dt_object *d,
         return d->do_body_ops->dbo_fiemap_get(env, d, fm);
 }
 
-static inline int dt_statfs(const struct lu_env *env, struct dt_device *dev,
-                           struct obd_statfs *osfs,
-                           struct obd_statfs_info *info)
+static inline int dt_statfs_info(const struct lu_env *env,
+                                struct dt_device *dev,
+                               struct obd_statfs *osfs,
+                               struct obd_statfs_info *info)
 {
        LASSERT(dev);
        LASSERT(dev->dd_ops);
@@ -2524,6 +2525,12 @@ static inline int dt_statfs(const struct lu_env *env, struct dt_device *dev,
        return dev->dd_ops->dt_statfs(env, dev, osfs, info);
 }
 
+static inline int dt_statfs(const struct lu_env *env, struct dt_device *dev,
+                           struct obd_statfs *osfs)
+{
+       return dt_statfs_info(env, dev, osfs, NULL);
+}
+
 static inline int dt_root_get(const struct lu_env *env, struct dt_device *dev,
                               struct lu_fid *f)
 {
index ceed008..8d9c1ef 100644 (file)
@@ -1331,7 +1331,7 @@ static int lod_statfs(const struct lu_env *env, struct dt_device *dev,
        u64 ost_ffree = 0;
        int i, rc, bs;
 
-       rc = dt_statfs(env, dt2lod_dev(dev)->lod_child, sfs, NULL);
+       rc = dt_statfs(env, dt2lod_dev(dev)->lod_child, sfs);
        if (rc)
                GOTO(out, rc);
 
@@ -1346,7 +1346,7 @@ static int lod_statfs(const struct lu_env *env, struct dt_device *dev,
        lod_foreach_mdt(lod, i) {
                mdt = MDT_TGT(lod, i);
                LASSERT(mdt && mdt->ltd_mdt);
-               rc = dt_statfs(env, mdt->ltd_mdt, &ost_sfs, NULL);
+               rc = dt_statfs(env, mdt->ltd_mdt, &ost_sfs);
                /* ignore errors */
                if (rc)
                        continue;
@@ -1365,7 +1365,7 @@ static int lod_statfs(const struct lu_env *env, struct dt_device *dev,
        lod_foreach_ost(lod, i) {
                ost = OST_TGT(lod, i);
                LASSERT(ost && ost->ltd_ost);
-               rc = dt_statfs(env, ost->ltd_ost, &ost_sfs, NULL);
+               rc = dt_statfs(env, ost->ltd_ost, &ost_sfs);
                /* ignore errors */
                if (rc || ost_sfs.os_bsize == 0)
                        continue;
index fcd9bfc..6cdc670 100644 (file)
@@ -705,9 +705,6 @@ __u16 lod_comp_entry_stripe_count(struct lod_object *lo,
 __u16 lod_get_stripe_count(struct lod_device *lod, struct lod_object *lo,
                           __u16 stripe_count, bool overstriping);
 void lod_qos_statfs_update(const struct lu_env *env, struct lod_device *lod);
-int lod_statfs_and_check(const struct lu_env *env, struct lod_device *d,
-                        int index, struct obd_statfs *sfs,
-                        struct obd_statfs_info *info);
 
 /* lproc_lod.c */
 int lod_procfs_init(struct lod_device *lod);
index dd5e8e1..d33a667 100644 (file)
@@ -2040,7 +2040,7 @@ static int lod_prep_md_striped_create(const struct lu_env *env,
                                continue;
 
                        tgt_dt = tgt->ltd_tgt;
-                       rc = dt_statfs(env, tgt_dt, &info->lti_osfs, NULL);
+                       rc = dt_statfs(env, tgt_dt, &info->lti_osfs);
                        if (rc) {
                                /* this OSP doesn't feel well */
                                rc = 0;
@@ -4303,6 +4303,9 @@ static int lod_layout_del_prep_layout(const struct lu_env *env,
 
        ENTRY;
 
+       LASSERT(lo->ldo_is_composite);
+       LASSERT(lo->ldo_comp_cnt > 0 && lo->ldo_comp_entries != NULL);
+
        rc = lod_layout_data_init(info, lo->ldo_comp_cnt);
        if (rc)
                RETURN(rc);
@@ -4412,9 +4415,7 @@ static int lod_layout_del(const struct lu_env *env, struct dt_object *dt,
        struct lu_attr *attr = &lod_env_info(env)->lti_attr;
        int rc;
 
-       LASSERT(lo->ldo_is_composite);
        LASSERT(lo->ldo_mirror_count == 1);
-       LASSERT(lo->ldo_comp_cnt > 0 && lo->ldo_comp_entries != NULL);
 
        rc = lod_layout_del_prep_layout(env, lo, th);
        if (rc < 0)
@@ -6354,7 +6355,7 @@ static bool lod_sel_osts_allowed(const struct lu_env *env,
                        break;
                }
 
-               rc = dt_statfs(env, ost->ltd_ost, sfs, &info);
+               rc = dt_statfs_info(env, ost->ltd_ost, sfs, &info);
                if (rc) {
                        CDEBUG(D_LAYOUT, "statfs failed for ost %d, error %d\n",
                               index, rc);
index 7d738f3..739720f 100644 (file)
@@ -78,9 +78,8 @@
  * \retval negative    negated errno on error
 
  */
-int lod_statfs_and_check(const struct lu_env *env, struct lod_device *d,
-                        int index, struct obd_statfs *sfs,
-                        struct obd_statfs_info *info)
+static int lod_statfs_and_check(const struct lu_env *env, struct lod_device *d,
+                               int index, struct obd_statfs *sfs)
 {
        struct lod_tgt_desc *ost;
        int                  rc;
@@ -90,7 +89,7 @@ int lod_statfs_and_check(const struct lu_env *env, struct lod_device *d,
        ost = OST_TGT(d,index);
        LASSERT(ost);
 
-       rc = dt_statfs(env, ost->ltd_ost, sfs, info);
+       rc = dt_statfs(env, ost->ltd_ost, sfs);
 
        if (rc == 0 && ((sfs->os_state & OS_STATE_ENOSPC) ||
            (sfs->os_state & OS_STATE_ENOINO && sfs->os_fprecreated == 0)))
@@ -180,7 +179,7 @@ void lod_qos_statfs_update(const struct lu_env *env, struct lod_device *lod)
                idx = osts->op_array[i];
                avail = OST_TGT(lod,idx)->ltd_statfs.os_bavail;
                if (lod_statfs_and_check(env, lod, idx,
-                                        &OST_TGT(lod, idx)->ltd_statfs, NULL))
+                                        &OST_TGT(lod, idx)->ltd_statfs))
                        continue;
                if (OST_TGT(lod,idx)->ltd_statfs.os_bavail != avail)
                        /* recalculate weigths */
@@ -832,7 +831,7 @@ static int lod_check_and_reserve_ost(const struct lu_env *env,
        int rc;
        ENTRY;
 
-       rc = lod_statfs_and_check(env, lod, ost_idx, sfs, NULL);
+       rc = lod_statfs_and_check(env, lod, ost_idx, sfs);
        if (rc)
                RETURN(rc);
 
@@ -1157,7 +1156,7 @@ static int lod_alloc_ost_list(const struct lu_env *env, struct lod_object *lo,
                        break;
                }
 
-               rc = lod_statfs_and_check(env, m, ost_idx, sfs, NULL);
+               rc = lod_statfs_and_check(env, m, ost_idx, sfs);
                if (rc < 0) /* this OSP doesn't feel well */
                        break;
 
@@ -1301,7 +1300,7 @@ repeat_find:
                 * start OST, then it can be skipped, otherwise skip it only
                 * if it is inactive/recovering/out-of-space." */
 
-               rc = lod_statfs_and_check(env, m, ost_idx, sfs, NULL);
+               rc = lod_statfs_and_check(env, m, ost_idx, sfs);
                if (rc) {
                        /* this OSP doesn't feel well */
                        continue;
@@ -1502,8 +1501,7 @@ static int lod_alloc_qos(const struct lu_env *env, struct lod_object *lo,
                ost = OST_TGT(lod, osts->op_array[i]);
                ost->ltd_qos.ltq_usable = 0;
 
-               rc = lod_statfs_and_check(env, lod, osts->op_array[i],
-                                         sfs, NULL);
+               rc = lod_statfs_and_check(env, lod, osts->op_array[i], sfs);
                if (rc) {
                        /* this OSP doesn't feel well */
                        continue;
index 680ce92..cb2c780 100644 (file)
@@ -680,7 +680,7 @@ static int lod_osts_seq_show(struct seq_file *p, void *v)
 
        /* XXX: should be non-NULL env, but it's very expensive */
        active = 1;
-       rc = dt_statfs(NULL, next, &sfs, NULL);
+       rc = dt_statfs(NULL, next, &sfs);
        if (rc == -ENOTCONN) {
                active = 0;
                rc = 0;
index 78a28d5..771f6eb 100644 (file)
@@ -456,7 +456,7 @@ static int mdt_statfs(struct tgt_session_info *tsi)
                                                              next, osfs);
                        else
                                rc = dt_statfs(info->mti_env, mdt->mdt_bottom,
-                                              osfs, NULL);
+                                              osfs);
                        if (rc)
                                GOTO(out, rc);
                        spin_lock(&mdt->mdt_lock);
index 49cb28b..3bec5f7 100644 (file)
@@ -995,7 +995,7 @@ int lprocfs_dt_blksize_seq_show(struct seq_file *m, void *v)
        struct dt_device *dt = m->private;
        struct obd_statfs osfs;
 
-       int rc = dt_statfs(NULL, dt, &osfs, NULL);
+       int rc = dt_statfs(NULL, dt, &osfs);
        if (rc == 0)
                seq_printf(m, "%u\n", (unsigned) osfs.os_bsize);
        return rc;
@@ -1007,7 +1007,7 @@ int lprocfs_dt_kbytestotal_seq_show(struct seq_file *m, void *v)
        struct dt_device *dt = m->private;
        struct obd_statfs osfs;
 
-       int rc = dt_statfs(NULL, dt, &osfs, NULL);
+       int rc = dt_statfs(NULL, dt, &osfs);
        if (rc == 0) {
                __u32 blk_size = osfs.os_bsize >> 10;
                __u64 result = osfs.os_blocks;
@@ -1026,7 +1026,7 @@ int lprocfs_dt_kbytesfree_seq_show(struct seq_file *m, void *v)
        struct dt_device *dt = m->private;
        struct obd_statfs osfs;
 
-       int rc = dt_statfs(NULL, dt, &osfs, NULL);
+       int rc = dt_statfs(NULL, dt, &osfs);
        if (rc == 0) {
                __u32 blk_size = osfs.os_bsize >> 10;
                __u64 result = osfs.os_bfree;
@@ -1045,7 +1045,7 @@ int lprocfs_dt_kbytesavail_seq_show(struct seq_file *m, void *v)
        struct dt_device *dt = m->private;
        struct obd_statfs osfs;
 
-       int rc = dt_statfs(NULL, dt, &osfs, NULL);
+       int rc = dt_statfs(NULL, dt, &osfs);
        if (rc == 0) {
                __u32 blk_size = osfs.os_bsize >> 10;
                __u64 result = osfs.os_bavail;
@@ -1064,7 +1064,7 @@ int lprocfs_dt_filestotal_seq_show(struct seq_file *m, void *v)
        struct dt_device *dt = m->private;
        struct obd_statfs osfs;
 
-       int rc = dt_statfs(NULL, dt, &osfs, NULL);
+       int rc = dt_statfs(NULL, dt, &osfs);
        if (rc == 0)
                seq_printf(m, "%llu\n", osfs.os_files);
        return rc;
@@ -1076,7 +1076,7 @@ int lprocfs_dt_filesfree_seq_show(struct seq_file *m, void *v)
        struct dt_device *dt = m->private;
        struct obd_statfs osfs;
 
-       int rc = dt_statfs(NULL, dt, &osfs, NULL);
+       int rc = dt_statfs(NULL, dt, &osfs);
        if (rc == 0)
                seq_printf(m, "%llu\n", osfs.os_ffree);
        return rc;
@@ -1107,7 +1107,7 @@ static ssize_t blocksize_show(struct kobject *kobj, struct attribute *attr,
        struct obd_statfs osfs;
        int rc;
 
-       rc = dt_statfs(NULL, dt, &osfs, NULL);
+       rc = dt_statfs(NULL, dt, &osfs);
        if (rc)
                return rc;
 
@@ -1125,7 +1125,7 @@ static ssize_t kbytestotal_show(struct kobject *kobj, struct attribute *attr,
        u64 result;
        int rc;
 
-       rc = dt_statfs(NULL, dt, &osfs, NULL);
+       rc = dt_statfs(NULL, dt, &osfs);
        if (rc)
                return rc;
 
@@ -1149,7 +1149,7 @@ static ssize_t kbytesfree_show(struct kobject *kobj, struct attribute *attr,
        u64 result;
        int rc;
 
-       rc = dt_statfs(NULL, dt, &osfs, NULL);
+       rc = dt_statfs(NULL, dt, &osfs);
        if (rc)
                return rc;
 
@@ -1173,7 +1173,7 @@ static ssize_t kbytesavail_show(struct kobject *kobj, struct attribute *attr,
        u64 result;
        int rc;
 
-       rc = dt_statfs(NULL, dt, &osfs, NULL);
+       rc = dt_statfs(NULL, dt, &osfs);
        if (rc)
                return rc;
 
@@ -1195,7 +1195,7 @@ static ssize_t filestotal_show(struct kobject *kobj, struct attribute *attr,
        struct obd_statfs osfs;
        int rc;
 
-       rc = dt_statfs(NULL, dt, &osfs, NULL);
+       rc = dt_statfs(NULL, dt, &osfs);
        if (rc)
                return rc;
 
@@ -1211,7 +1211,7 @@ static ssize_t filesfree_show(struct kobject *kobj, struct attribute *attr,
        struct obd_statfs osfs;
        int rc;
 
-       rc = dt_statfs(NULL, dt, &osfs, NULL);
+       rc = dt_statfs(NULL, dt, &osfs);
        if (rc)
                return rc;
 
index a56947a..c5b15f1 100644 (file)
@@ -195,7 +195,7 @@ static int llog_cat_new_log(const struct lu_env *env,
        /* 2MB for the cases when free space hasn't been learned yet */
        loghandle->lgh_max_size = 2 << 20;
        dt = lu2dt_dev(cathandle->lgh_obj->do_lu.lo_dev);
-       rc = dt_statfs(env, dt, &lgi->lgi_statfs, NULL);
+       rc = dt_statfs(env, dt, &lgi->lgi_statfs);
        if (rc == 0 && lgi->lgi_statfs.os_bfree > 0) {
                __u64 freespace = (lgi->lgi_statfs.os_bfree *
                                  lgi->lgi_statfs.os_bsize) >> 6;
index 6d62e82..42af490 100644 (file)
@@ -1657,7 +1657,7 @@ static int server_statfs(struct dentry *dentry, struct kstatfs *buf)
        ENTRY;
 
        if (lsi->lsi_dt_dev) {
-               rc = dt_statfs(NULL, lsi->lsi_dt_dev, &statfs, NULL);
+               rc = dt_statfs(NULL, lsi->lsi_dt_dev, &statfs);
                if (rc == 0) {
                        statfs_unpack(buf, &statfs);
                        buf->f_type = sb->s_magic;
index c5d9f2e..478854c 100644 (file)
@@ -1434,7 +1434,7 @@ static int ofd_health_check(const struct lu_env *nul, struct obd_device *obd)
                RETURN(rc);
 
        info = ofd_info_init(&env, NULL);
-       rc = dt_statfs(&env, ofd->ofd_osd, &info->fti_u.osfs, NULL);
+       rc = dt_statfs(&env, ofd->ofd_osd, &info->fti_u.osfs);
        if (unlikely(rc))
                GOTO(out, rc);
 
index 34f1760..e832bc9 100644 (file)
@@ -309,7 +309,7 @@ int tgt_statfs_internal(const struct lu_env *env, struct lu_target *lut,
 
                /* statfs can sleep ... hopefully not for too long since we can
                 * call it fairly often as space fills up */
-               rc = dt_statfs(env, lut->lut_bottom, osfs, NULL);
+               rc = dt_statfs(env, lut->lut_bottom, osfs);
                if (unlikely(rc))
                        GOTO(out, rc);
 
index 0ab28ba..bc7c508 100755 (executable)
@@ -662,11 +662,8 @@ test_1a() {
 }
 run_test 1a "mmap & cat a HSM released file"
 
-test_1b() {
-       mkdir -p $DIR/$tdir
-       $LFS setstripe -E 1M -S 1M -E 64M -c 2 -E -1 -c 4 $DIR/$tdir ||
-               error "failed to set default stripe"
-       local f=$DIR/$tdir/$tfile
+test_1bde_base() {
+       local f=$1
        rm -f $f
 
        dd if=/dev/urandom of=$f bs=1M count=1 conv=sync ||
@@ -690,6 +687,15 @@ test_1b() {
        echo "verify restored state: "
        check_hsm_flags $f "0x00000009" && echo "pass"
 }
+
+test_1b() {
+       mkdir -p $DIR/$tdir
+       $LFS setstripe -E 1M -S 1M -E 64M -c 2 -E -1 -c 4 $DIR/$tdir ||
+               error "failed to set default stripe"
+       local f=$DIR/$tdir/$tfile
+
+       test_1bde_base $f
+}
 run_test 1b "Archive, Release and Restore composite file"
 
 test_1c() {
@@ -760,30 +766,49 @@ test_1d() {
        $LFS setstripe -E 1M -L mdt -E -1 -c 2 $DIR/$tdir ||
                error "failed to set default stripe"
        local f=$DIR/$tdir/$tfile
-       rm -f $f
 
-       dd if=/dev/urandom of=$f bs=1M count=1 conv=sync ||
-               error "failed to create file"
-       local fid=$(path2fid $f)
+       test_1bde_base $f
+}
+run_test 1d "Archive, Release and Restore DoM file"
 
-       copytool setup
+test_1e() {
+       [ $(lustre_version_code $SINGLEMDS) -lt $(version_code $SEL_VER) ] &&
+               skip "skipped for lustre < $SEL_VER"
 
-       echo "archive $f"
-       $LFS hsm_archive $f || error "could not archive file"
-       wait_request_state $fid ARCHIVE SUCCEED
+       mkdir -p $DIR/$tdir
+       $LFS setstripe -E 1G -z 64M -E 10G -z 512M -E -1 -z 1G $DIR/$tdir ||
+               error "failed to set default stripe"
+       local comp_file=$DIR/$tdir/$tfile
 
-       echo "release $f"
-       $LFS hsm_release $f || error "could not release file"
-       echo "verify released state: "
-       check_hsm_flags $f "0x0000000d" && echo "pass"
+       test_1bde_base $comp_file
 
-       echo "restore $f"
-       $LFS hsm_restore $f || error "could not restore file"
-       wait_request_state $fid RESTORE SUCCEED
-       echo "verify restored state: "
-       check_hsm_flags $f "0x00000009" && echo "pass"
+       local flg_opts="--comp-start 0 -E 64M --comp-flags init"
+       local found=$($LFS find $flg_opts $comp_file | wc -l)
+       [ $found -eq 1 ] || error "1st component not found"
+
+       flg_opts="--comp-start 64M -E 1G --comp-flags extension"
+       found=$($LFS find $flg_opts $comp_file | wc -l)
+       [ $found -eq 1 ] || error "2nd component not found"
+
+       flg_opts="--comp-start 1G -E 1G --comp-flags ^init"
+       found=$($LFS find $flg_opts $comp_file | wc -l)
+       [ $found -eq 1 ] || error "3rd component not found"
+
+       flg_opts="--comp-start 1G -E 10G --comp-flags extension"
+       found=$($LFS find $flg_opts $comp_file | wc -l)
+       [ $found -eq 1 ] || error "4th component not found"
+
+       flg_opts="--comp-start 10G -E 10G --comp-flags ^init"
+       found=$($LFS find $flg_opts $comp_file | wc -l)
+       [ $found -eq 1 ] || error "5th component not found"
+
+       flg_opts="--comp-start 10G -E EOF --comp-flags extension"
+       found=$($LFS find $flg_opts $comp_file | wc -l)
+       [ $found -eq 1 ] || error "6th component not found"
+
+       sel_layout_sanity $comp_file 6
 }
-run_test 1d "Archive, Release and Restore DoM file"
+run_test 1e "Archive, Release and Restore SEL file"
 
 test_2() {
        local f=$DIR/$tdir/$tfile
index 6a0665d..9c71449 100644 (file)
@@ -1271,17 +1271,25 @@ test_19g() {
 
        $LFS setstripe --component-add -E 1G -c 1 $file1 ||
                error "comp-add [0,1G] failed $file1"
+       $LFS setstripe --component-add -E 512M -z 128M $file1 &&
+               error "comp-add [1G,1G],SEL[1G,512M] succeded $file1"
        $LFS setstripe --component-add -E 10G -z 128M $file1 ||
                error "comp-add [1G,1G],SEL[1G,10G] failed $file1"
        $LFS setstripe --component-add -E -1 $file1 ||
                error "comp-add [10G,-1] failed $file1"
 
+       $LFS setstripe --component-add -E 1G -z 32M -c 1 $file2 &&
+               error "comp-add with smal ext size succeeded $file1"
+       $LFS setstripe --component-add -E 1G -z 100M -c 1 $file2 &&
+               error "comp-add with not aligned ext size succeeded $file1"
        $LFS setstripe --component-add -E 1G -z 128M -c 1 $file2 ||
                error "comp-add [0,128M],SEL[128M,1G] failed $file1"
        $LFS setstripe --component-add -E 10G $file2 ||
                error "comp-add [1G,10G] failed $file1"
        $LFS setstripe --component-add -E -1 -z 128M -c 1 $file2 ||
                error "comp-add [10G,10G],SEL[10G,-1] failed $file1"
+       $LFS setstripe --component-add -E -1 -z 128M -c 1 $file2 &&
+               error "repeated comp-add [10G,10G],SEL[10G,-1] succeeded $file1"
 
        $LFS getstripe $file1
        flg_opts="--comp-flags init"
index b3662cb..5ff220c 100644 (file)
@@ -1574,9 +1574,14 @@ int llapi_layout_file_open(const char *path, int open_flags, mode_t mode,
                return -1;
        }
 
-       if (layout && llapi_layout_sanity((struct llapi_layout *)layout, false,
-                                         !!(layout->llot_mirror_count > 1)))
-               return -1;
+       if (layout) {
+               rc = llapi_layout_sanity((struct llapi_layout *)layout, false,
+                                        !!(layout->llot_mirror_count > 1));
+               if (rc) {
+                       llapi_layout_sanity_perror(rc);
+                       return -1;
+               }
+       }
 
        /* Object creation must be postponed until after layout attributes
         * have been applied. */
@@ -2201,8 +2206,10 @@ int llapi_layout_file_comp_add(const char *path,
                goto out;
        }
 
-       if (llapi_layout_sanity(existing_layout, false, false)) {
+       rc = llapi_layout_sanity(existing_layout, false, false);
+       if (rc) {
                tmp_errno = errno;
+               llapi_layout_sanity_perror(rc);
                rc = -1;
                goto out;
        }
@@ -2334,8 +2341,10 @@ int llapi_layout_file_comp_del(const char *path, uint32_t id, uint32_t flags)
                goto out;
        }
 
-       if (llapi_layout_sanity(existing_layout, false, false)) {
+       rc = llapi_layout_sanity(existing_layout, false, false);
+       if (rc) {
                tmp_errno = errno;
+               llapi_layout_sanity_perror(rc);
                rc = -1;
                goto out;
        }
@@ -2492,8 +2501,10 @@ int llapi_layout_file_comp_set(const char *path, uint32_t *ids, uint32_t *flags,
                goto out;
        }
 
-       if (llapi_layout_sanity(existing_layout, false, false)) {
+       rc = llapi_layout_sanity(existing_layout, false, false);
+       if (rc) {
                tmp_errno = errno;
+               llapi_layout_sanity_perror(rc);
                rc = -1;
                goto out;
        }
@@ -2970,6 +2981,42 @@ enum llapi_layout_comp_sanity_error {
        LSE_START_GT_END,
        LSE_ALIGN_END,
        LSE_ALIGN_EXT,
+       LSE_LAST,
+};
+
+const char *llapi_layout_strerror[] =
+{
+       [LSE_OK] = "",
+       [LSE_INCOMPLETE_MIRROR] =
+               "Incomplete mirror - must go to EOF",
+       [LSE_ADJACENT_EXTENSION] =
+               "No adjacent extension space components",
+       [LSE_INIT_EXTENSION] =
+               "Cannot apply extension flag to init components",
+       [LSE_FLAGS] =
+               "Wrong flags",
+       [LSE_DOM_EXTENSION] =
+               "DoM components can't be extension space",
+       [LSE_DOM_EXTENSION_FOLLOWING] =
+               "DoM components cannot be followed by extension space",
+       [LSE_DOM_FLR] =
+               "FLR and DoM are not supported together",
+       [LSE_SET_COMP_START] =
+               "Must set previous component extent before adding next",
+       [LSE_NOT_ZERO_LENGTH_EXTENDABLE] =
+               "Extendable component must start out zero-length",
+       [LSE_END_NOT_GREATER] =
+               "Component end is before end of previous component",
+       [LSE_ZERO_LENGTH_NORMAL] =
+               "Zero length components must be followed by extension",
+       [LSE_NOT_ADJACENT_PREV] =
+               "Components not adjacent (end != next->start",
+       [LSE_START_GT_END] =
+               "Component start is > end",
+       [LSE_ALIGN_END] =
+               "The component end must be aligned by the stripe size",
+       [LSE_ALIGN_EXT] =
+               "The extension size must be aligned by the stripe size",
 };
 
 struct llapi_layout_sanity_args {
@@ -3101,7 +3148,7 @@ static int llapi_layout_sanity_cb(struct llapi_layout *layout,
 
                /* Components not followed by ext space must have length > 0. */
                if (comp->llc_extent.e_start == comp->llc_extent.e_end &&
-                   next && !(next->llc_flags & LCME_FL_EXTENSION)) {
+                   (next == NULL || !(next->llc_flags & LCME_FL_EXTENSION))) {
                        args->lsa_rc = LSE_ZERO_LENGTH_NORMAL;
                        goto out_err;
                }
@@ -3152,62 +3199,13 @@ out_err:
 /* Print explanation of layout error */
 void llapi_layout_sanity_perror(int error)
 {
-       char *msg = NULL;
-
-       switch (error) {
-       case LSE_OK:
-               break;
-       case LSE_INCOMPLETE_MIRROR:
-               msg = "Incomplete mirror - must go to EOF";
-               break;
-       case LSE_ADJACENT_EXTENSION:
-               msg = "No adjacent extension space components";
-               break;
-       case LSE_INIT_EXTENSION:
-               msg = "Cannot apply extension flag to init components";
-               break;
-       case LSE_FLAGS:
-               msg = "Wrong flags";
-               break;
-       case LSE_DOM_EXTENSION:
-               msg = "DoM components can't be extension space";
-               break;
-       case LSE_DOM_EXTENSION_FOLLOWING:
-               msg = "DoM components cannot be followed by extension space";
-               break;
-       case LSE_DOM_FLR:
-               msg = "FLR and DoM are not supported together";
-               break;
-       case LSE_SET_COMP_START:
-               msg = "Must set previous component extent before adding next";
-               break;
-       case LSE_NOT_ZERO_LENGTH_EXTENDABLE:
-               msg = "Extendable component must start out zero-length";
-               break;
-       case LSE_END_NOT_GREATER:
-               msg = "Component end is before end of previous component";
-               break;
-       case LSE_ZERO_LENGTH_NORMAL:
-               msg = "Zero length components must be followed by extension";
-               break;
-       case LSE_NOT_ADJACENT_PREV:
-               msg = "Components not adjacent (end != next->start";
-               break;
-       case LSE_START_GT_END:
-               msg = "Component start is > end";
-       case LSE_ALIGN_END:
-               msg = "The component end must be aligned by the stripe size";
-               break;
-       case LSE_ALIGN_EXT:
-               msg = "The extension size must be aligned by the stripe size";
-               break;
-       default:
+       if (error >= LSE_LAST || error < 0) {
                fprintf(stdout, "Invalid layout, unrecognized error: %d\n",
                        error);
+       } else {
+               fprintf(stdout, "Invalid layout: %s\n",
+                       llapi_layout_strerror[error]);
        }
-
-       if (msg)
-               fprintf(stdout, "Invalid layout: %s\n", msg);
 }
 
 /* Walk a layout and enforce sanity checks that apply to > 1 component