Whamcloud - gitweb
LU-14316 llite: quiet spurious ioctl warning
[fs/lustre-release.git] / lustre / lov / lov_pack.c
index da41b2c..c0d5745 100644 (file)
@@ -53,13 +53,13 @@ void lov_dump_lmm_common(int level, void *lmmp)
        struct ost_id oi;
 
        lmm_oi_le_to_cpu(&oi, &lmm->lmm_oi);
-       CDEBUG(level, "objid "DOSTID", magic 0x%08x, pattern %#x\n",
-              POSTID(&oi), le32_to_cpu(lmm->lmm_magic),
-              le32_to_cpu(lmm->lmm_pattern));
-       CDEBUG(level, "stripe_size %u, stripe_count %u, layout_gen %u\n",
-              le32_to_cpu(lmm->lmm_stripe_size),
-              le16_to_cpu(lmm->lmm_stripe_count),
-              le16_to_cpu(lmm->lmm_layout_gen));
+       CDEBUG_LIMIT(level, "objid "DOSTID", magic 0x%08x, pattern %#x\n",
+                    POSTID(&oi), le32_to_cpu(lmm->lmm_magic),
+                    le32_to_cpu(lmm->lmm_pattern));
+       CDEBUG_LIMIT(level, "stripe_size %u, stripe_count %u, layout_gen %u\n",
+                    le32_to_cpu(lmm->lmm_stripe_size),
+                    le16_to_cpu(lmm->lmm_stripe_count),
+                    le16_to_cpu(lmm->lmm_layout_gen));
 }
 
 static void lov_dump_lmm_objects(int level, struct lov_ost_data *lod,
@@ -68,8 +68,9 @@ static void lov_dump_lmm_objects(int level, struct lov_ost_data *lod,
        int i;
 
        if (stripe_count > LOV_V1_INSANE_STRIPE_COUNT) {
-               CDEBUG(level, "bad stripe_count %u > max_stripe_count %u\n",
-                      stripe_count, LOV_V1_INSANE_STRIPE_COUNT);
+               CDEBUG_LIMIT(level,
+                            "bad stripe_count %u > max_stripe_count %u\n",
+                            stripe_count, LOV_V1_INSANE_STRIPE_COUNT);
                return;
        }
 
@@ -77,8 +78,8 @@ static void lov_dump_lmm_objects(int level, struct lov_ost_data *lod,
                struct ost_id oi;
 
                ostid_le_to_cpu(&lod->l_ost_oi, &oi);
-               CDEBUG(level, "stripe %u idx %u subobj "DOSTID"\n", i,
-                      le32_to_cpu(lod->l_ost_idx), POSTID(&oi));
+               CDEBUG_LIMIT(level, "stripe %u idx %u subobj "DOSTID"\n", i,
+                            le32_to_cpu(lod->l_ost_idx), POSTID(&oi));
        }
 }
 
@@ -89,34 +90,6 @@ void lov_dump_lmm_v1(int level, struct lov_mds_md_v1 *lmm)
                             le16_to_cpu(lmm->lmm_stripe_count));
 }
 
-void lov_dump_lmm_v3(int level, struct lov_mds_md_v3 *lmm)
-{
-       lov_dump_lmm_common(level, lmm);
-       CDEBUG(level, "pool_name "LOV_POOLNAMEF"\n", lmm->lmm_pool_name);
-       lov_dump_lmm_objects(level, lmm->lmm_objects,
-                            le16_to_cpu(lmm->lmm_stripe_count));
-}
-
-void lov_dump_lmm(int level, void *lmm)
-{
-       int magic;
-
-       magic = le32_to_cpu(((struct lov_mds_md *)lmm)->lmm_magic);
-       switch (magic) {
-       case LOV_MAGIC_V1:
-               lov_dump_lmm_v1(level, (struct lov_mds_md_v1 *)lmm);
-               break;
-       case LOV_MAGIC_V3:
-               lov_dump_lmm_v3(level, (struct lov_mds_md_v3 *)lmm);
-               break;
-       default:
-               CDEBUG(level, "unrecognized lmm_magic %x, assuming %x\n",
-                      magic, LOV_MAGIC_V1);
-               lov_dump_lmm_common(level, lmm);
-               break;
-       }
-}
-
 /**
  * Pack LOV striping metadata for disk storage format (in little
  * endian byte order).
@@ -125,8 +98,8 @@ void lov_dump_lmm(int level, void *lmm)
  * then return the size needed. If \a buf_size is too small then
  * return -ERANGE. Otherwise return the size of the result.
  */
-ssize_t lov_lsm_pack_v1v3(const struct lov_stripe_md *lsm, void *buf,
-                         size_t buf_size)
+static ssize_t lov_lsm_pack_v1v3(const struct lov_stripe_md *lsm, void *buf,
+                                size_t buf_size)
 {
        struct lov_mds_md_v1 *lmmv1 = buf;
        struct lov_mds_md_v3 *lmmv3 = buf;
@@ -158,8 +131,8 @@ ssize_t lov_lsm_pack_v1v3(const struct lov_stripe_md *lsm, void *buf,
        lmmv1->lmm_layout_gen = cpu_to_le16(lsm->lsm_layout_gen);
 
        if (lsm->lsm_magic == LOV_MAGIC_V3) {
-               CLASSERT(sizeof(lsm->lsm_entries[0]->lsme_pool_name) ==
-                        sizeof(lmmv3->lmm_pool_name));
+               BUILD_BUG_ON(sizeof(lsm->lsm_entries[0]->lsme_pool_name) !=
+                                   sizeof(lmmv3->lmm_pool_name));
                strlcpy(lmmv3->lmm_pool_name,
                        lsm->lsm_entries[0]->lsme_pool_name,
                        sizeof(lmmv3->lmm_pool_name));
@@ -182,6 +155,28 @@ ssize_t lov_lsm_pack_v1v3(const struct lov_stripe_md *lsm, void *buf,
        RETURN(lmm_size);
 }
 
+static ssize_t lov_lsm_pack_foreign(const struct lov_stripe_md *lsm, void *buf,
+                                   size_t buf_size)
+{
+       struct lov_foreign_md *lfm = buf;
+       size_t lfm_size;
+
+       lfm_size = lsm->lsm_foreign_size;
+
+       if (buf_size == 0)
+               RETURN(lfm_size);
+
+       if (buf_size < lfm_size)
+               RETURN(-ERANGE);
+
+       /* full foreign LOV is already avail in its cache
+        * no need to translate format fields to little-endian
+        */
+       memcpy(lfm, lsm_foreign(lsm), lsm->lsm_foreign_size);
+
+       RETURN(lfm_size);
+}
+
 ssize_t lov_lsm_pack(const struct lov_stripe_md *lsm, void *buf,
                     size_t buf_size)
 {
@@ -199,6 +194,9 @@ ssize_t lov_lsm_pack(const struct lov_stripe_md *lsm, void *buf,
        if (lsm->lsm_magic == LOV_MAGIC_V1 || lsm->lsm_magic == LOV_MAGIC_V3)
                return lov_lsm_pack_v1v3(lsm, buf, buf_size);
 
+       if (lsm->lsm_magic == LOV_MAGIC_FOREIGN)
+               return lov_lsm_pack_foreign(lsm, buf, buf_size);
+
        lmm_size = lov_comp_md_size(lsm);
        if (buf_size == 0)
                RETURN(lmm_size);
@@ -361,29 +359,22 @@ int lov_getstripe(const struct lu_env *env, struct lov_object *obj,
 {
        /* we use lov_user_md_v3 because it is larger than lov_user_md_v1 */
        struct lov_mds_md *lmmk, *lmm;
+       struct lov_foreign_md *lfm;
        struct lov_user_md_v1 lum;
-       size_t lmmk_size;
-       ssize_t lmm_size, lum_size = 0;
-       static bool printed;
+       size_t lmmk_size, lum_size = 0;
+       ssize_t lmm_size;
        int rc = 0;
 
        ENTRY;
 
        if (lsm->lsm_magic != LOV_MAGIC_V1 && lsm->lsm_magic != LOV_MAGIC_V3 &&
-           lsm->lsm_magic != LOV_MAGIC_COMP_V1) {
+           lsm->lsm_magic != LOV_MAGIC_COMP_V1 &&
+           lsm->lsm_magic != LOV_MAGIC_FOREIGN) {
                CERROR("bad LSM MAGIC: 0x%08X != 0x%08X nor 0x%08X\n",
                       lsm->lsm_magic, LOV_MAGIC_V1, LOV_MAGIC_V3);
                GOTO(out, rc = -EIO);
        }
 
-       if (!printed) {
-               LCONSOLE_WARN("%s: using old ioctl(LL_IOC_LOV_GETSTRIPE) on "
-                             DFID", use llapi_layout_get_by_path()\n",
-                             current->comm,
-                             PFID(&obj->lo_cl.co_lu.lo_header->loh_fid));
-               printed = true;
-       }
-
        lmmk_size = lov_comp_md_size(lsm);
 
        OBD_ALLOC_LARGE(lmmk, lmmk_size);
@@ -404,6 +395,12 @@ int lov_getstripe(const struct lu_env *env, struct lov_object *obj,
                } else if (lmmk->lmm_magic == cpu_to_le32(LOV_MAGIC_COMP_V1)) {
                        lustre_swab_lov_comp_md_v1(
                                        (struct lov_comp_md_v1 *)lmmk);
+               } else if (lmmk->lmm_magic == cpu_to_le32(LOV_MAGIC_FOREIGN)) {
+                       lfm = (struct lov_foreign_md *)lmmk;
+                       __swab32s(&lfm->lfm_magic);
+                       __swab32s(&lfm->lfm_length);
+                       __swab32s(&lfm->lfm_type);
+                       __swab32s(&lfm->lfm_flags);
                }
        }
 
@@ -411,8 +408,9 @@ int lov_getstripe(const struct lu_env *env, struct lov_object *obj,
         * Legacy appication passes limited buffer, we need to figure out
         * the user buffer size by the passed in lmm_stripe_count.
         */
-       if (copy_from_user(&lum, lump, sizeof(struct lov_user_md_v1)))
-               GOTO(out_free, rc = -EFAULT);
+       if (lsm->lsm_magic != LOV_MAGIC_FOREIGN)
+               if (copy_from_user(&lum, lump, sizeof(struct lov_user_md_v1)))
+                       GOTO(out_free, rc = -EFAULT);
 
        if (lum.lmm_magic == LOV_USER_MAGIC_V1 ||
            lum.lmm_magic == LOV_USER_MAGIC_V3)
@@ -453,14 +451,23 @@ int lov_getstripe(const struct lu_env *env, struct lov_object *obj,
                                i--;
                        comp_md = (struct lov_mds_md *)((char *)comp_v1 +
                                        comp_v1->lcm_entries[i].lcme_offset);
+                       lum_size = comp_v1->lcm_entries[i].lcme_size;
                }
 
                lmm = comp_md;
-               lmm_size = lum_size;
+               lmm_size = min(lum_size, lmmk_size);
        } else {
                lmm = lmmk;
                lmm_size = lmmk_size;
        }
+
+       /**
+        * Return stripe_count=1 instead of 0 for DoM files to avoid
+        * divide-by-zero for older userspace that calls this ioctl,
+        * e.g. lustre ADIO driver.
+        */
+       if ((lum.lmm_stripe_count == 0) && (lum.lmm_pattern & LOV_PATTERN_MDT))
+               lum.lmm_stripe_count = 1;
        /**
         * User specified limited buffer size, usually the buffer is
         * from ll_lov_setstripe(), and the buffer can only hold basic