struct lov_mds_md **lmmp, int *lmm_size,
struct ptlrpc_request **request)
{
- struct ll_sb_info *sbi = ll_i2sbi(inode);
- struct mdt_body *body;
- struct lov_mds_md *lmm = NULL;
- struct ptlrpc_request *req = NULL;
- struct md_op_data *op_data;
- int rc, lmmsize;
+ struct ll_sb_info *sbi = ll_i2sbi(inode);
+ struct mdt_body *body;
+ struct lov_mds_md *lmm = NULL;
+ struct ptlrpc_request *req = NULL;
+ struct md_op_data *op_data;
+ int rc, lmmsize;
+
+ ENTRY;
rc = ll_get_default_mdsize(sbi, &lmmsize);
if (rc)
RETURN(rc);
- op_data = ll_prep_md_op_data(NULL, inode, NULL, filename,
- strlen(filename), lmmsize,
- LUSTRE_OPC_ANY, NULL);
- if (IS_ERR(op_data))
- RETURN(PTR_ERR(op_data));
+ op_data = ll_prep_md_op_data(NULL, inode, NULL, filename,
+ strlen(filename), lmmsize,
+ LUSTRE_OPC_ANY, NULL);
+ if (IS_ERR(op_data))
+ RETURN(PTR_ERR(op_data));
- op_data->op_valid = OBD_MD_FLEASIZE | OBD_MD_FLDIREA;
- rc = md_getattr_name(sbi->ll_md_exp, op_data, &req);
- ll_finish_md_op_data(op_data);
- if (rc < 0) {
- CDEBUG(D_INFO, "md_getattr_name failed "
- "on %s: rc %d\n", filename, rc);
- GOTO(out, rc);
- }
+ op_data->op_valid = OBD_MD_FLEASIZE | OBD_MD_FLDIREA;
+ rc = md_getattr_name(sbi->ll_md_exp, op_data, &req);
+ ll_finish_md_op_data(op_data);
+ if (rc < 0) {
+ CDEBUG(D_INFO, "md_getattr_name failed "
+ "on %s: rc %d\n", filename, rc);
+ GOTO(out, rc);
+ }
- body = req_capsule_server_get(&req->rq_pill, &RMF_MDT_BODY);
- LASSERT(body != NULL); /* checked by mdc_getattr_name */
+ body = req_capsule_server_get(&req->rq_pill, &RMF_MDT_BODY);
+ LASSERT(body != NULL); /* checked by mdc_getattr_name */
lmmsize = body->mbo_eadatasize;
if (!(body->mbo_valid & (OBD_MD_FLEASIZE | OBD_MD_FLDIREA)) ||
- lmmsize == 0) {
- GOTO(out, rc = -ENODATA);
- }
+ lmmsize == 0)
+ GOTO(out, rc = -ENODATA);
- lmm = req_capsule_server_sized_get(&req->rq_pill, &RMF_MDT_MD, lmmsize);
- LASSERT(lmm != NULL);
+ lmm = req_capsule_server_sized_get(&req->rq_pill, &RMF_MDT_MD, lmmsize);
+ LASSERT(lmm != NULL);
if (lmm->lmm_magic != cpu_to_le32(LOV_MAGIC_V1) &&
lmm->lmm_magic != cpu_to_le32(LOV_MAGIC_V3) &&
/*
* This is coming from the MDS, so is probably in
- * little endian. We convert it to host endian before
+ * little endian. We convert it to host endian before
* passing it to userspace.
*/
- if ((lmm->lmm_magic & __swab32(LOV_MAGIC_MAGIC)) ==
- __swab32(LOV_MAGIC_MAGIC)) {
+ if (cpu_to_le32(LOV_MAGIC) != LOV_MAGIC) {
int stripe_count = 0;
if (lmm->lmm_magic == cpu_to_le32(LOV_MAGIC_V1) ||
if (le32_to_cpu(lmm->lmm_pattern) &
LOV_PATTERN_F_RELEASED)
stripe_count = 0;
- }
-
- lustre_swab_lov_user_md((struct lov_user_md *)lmm, 0);
+ lustre_swab_lov_user_md((struct lov_user_md *)lmm, 0);
- /* if function called for directory - we should
- * avoid swab not existent lsm objects */
- if (lmm->lmm_magic == LOV_MAGIC_V1 && S_ISREG(body->mbo_mode))
- lustre_swab_lov_user_md_objects(
+ /* if function called for directory - we should
+ * avoid swab not existent lsm objects
+ */
+ if (lmm->lmm_magic == LOV_MAGIC_V1 &&
+ S_ISREG(body->mbo_mode))
+ lustre_swab_lov_user_md_objects(
((struct lov_user_md_v1 *)lmm)->lmm_objects,
stripe_count);
- else if (lmm->lmm_magic == LOV_MAGIC_V3 &&
- S_ISREG(body->mbo_mode))
- lustre_swab_lov_user_md_objects(
+ else if (lmm->lmm_magic == LOV_MAGIC_V3 &&
+ S_ISREG(body->mbo_mode))
+ lustre_swab_lov_user_md_objects(
((struct lov_user_md_v3 *)lmm)->lmm_objects,
stripe_count);
+ } else if (lmm->lmm_magic == cpu_to_le32(LOV_MAGIC_COMP_V1)) {
+ lustre_swab_lov_comp_md_v1(
+ (struct lov_comp_md_v1 *)lmm);
+ }
}
+ if (lmm->lmm_magic == LOV_MAGIC_COMP_V1) {
+ struct lov_comp_md_v1 *comp_v1 = NULL;
+ struct lov_comp_md_entry_v1 *ent;
+ struct lov_user_md_v1 *v1;
+ __u32 off;
+ int i = 0;
+
+ comp_v1 = (struct lov_comp_md_v1 *)lmm;
+ /* Dump the striping information */
+ for (; i < comp_v1->lcm_entry_count; i++) {
+ ent = &comp_v1->lcm_entries[i];
+ off = ent->lcme_offset;
+ v1 = (struct lov_user_md_v1 *)((char *)lmm + off);
+ CDEBUG(D_INFO,
+ "comp[%d]: stripe_count=%u, stripe_size=%u\n",
+ i, v1->lmm_stripe_count, v1->lmm_stripe_size);
+ }
+
+ /**
+ * Return valid stripe_count and stripe_size instead of 0 for
+ * DoM files to avoid divide-by-zero for older userspace that
+ * calls this ioctl, e.g. lustre ADIO driver.
+ */
+ if (lmm->lmm_stripe_count == 0)
+ lmm->lmm_stripe_count = 1;
+ if (lmm->lmm_stripe_size == 0) {
+ /* Since the first component of the file data is placed
+ * on the MDT for faster access, the stripe_size of the
+ * second one is always that applications which are
+ * doing large IOs.
+ */
+ if (lmm->lmm_pattern == LOV_PATTERN_MDT)
+ i = comp_v1->lcm_entry_count > 1 ? 1 : 0;
+ else
+ i = comp_v1->lcm_entry_count > 1 ?
+ comp_v1->lcm_entry_count - 1 : 0;
+ ent = &comp_v1->lcm_entries[i];
+ off = ent->lcme_offset;
+ v1 = (struct lov_user_md_v1 *)((char *)lmm + off);
+ lmm->lmm_stripe_size = v1->lmm_stripe_size;
+ }
+ }
out:
*lmmp = lmm;
*lmm_size = lmmsize;
*request = req;
- return rc;
+ RETURN(rc);
}
static int ll_lov_setea(struct inode *inode, struct file *file,
--- /dev/null
+/*
+ * GPL HEADER START
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 only,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License version 2 for more details (a copy is included
+ * in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License
+ * version 2 along with this program; If not, see
+ * http://www.gnu.org/licenses/gpl-2.0.html
+ *
+ * GPL HEADER END
+ */
+/*
+ * Copyright (c) 2021, DDN Storage Corporation.
+ */
+/*
+ * lustre/tests/lov_getstripe_old.c
+ *
+ * ll_getstripe_old <file>:
+ * - to verify if the striping information of composite layout files returned
+ * by llapi_file_get_stripe() is valid.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <sys/vfs.h>
+#include <lustre/lustreapi.h>
+#define LOV_MAGIC_MAGIC 0x0BD0
+#define LOV_MAGIC_MASK 0xFFFF
+#define LOV_MAGIC_V1 (0x0BD10000 | LOV_MAGIC_MAGIC)
+#define LOV_MAGIC_JOIN_V1 (0x0BD20000 | LOV_MAGIC_MAGIC)
+#define LOV_MAGIC_V3 (0x0BD30000 | LOV_MAGIC_MAGIC)
+static inline int maxint(int a, int b)
+{
+ return a > b ? a : b;
+}
+
+static void *alloc_lum()
+{
+ int v1, v3;
+
+ v1 = sizeof(struct lov_user_md_v1) +
+ LOV_MAX_STRIPE_COUNT * sizeof(struct lov_user_ost_data_v1);
+ v3 = sizeof(struct lov_user_md_v3) +
+ LOV_MAX_STRIPE_COUNT * sizeof(struct lov_user_ost_data_v1);
+
+ return malloc(maxint(v1, v3));
+}
+
+int main(int argc, char **argv)
+{
+ struct lov_user_md *lum_file = NULL;
+ int rc;
+
+ if (argc != 2) {
+ fprintf(stderr, "Usage: %s <filename>\n", argv[0]);
+ return 1;
+ }
+ lum_file = alloc_lum();
+ if (lum_file == NULL) {
+ rc = ENOMEM;
+ goto cleanup;
+ }
+
+ rc = llapi_file_get_stripe(argv[1], lum_file);
+ if (rc) {
+ rc = errno;
+ goto cleanup;
+ }
+ /* stripe_size stripe_count */
+ if (lum_file->lmm_magic == LOV_MAGIC_V1)
+ printf("lmm_magic: v1\n");
+ else if (lum_file->lmm_magic == LOV_MAGIC_V3)
+ printf("lmm_magic: v3\n");
+ else if (lum_file->lmm_magic == (0x0BD60000 | LOV_MAGIC_MAGIC))
+ printf("lmm_magic: LOV_MAGIC component\n");
+
+ printf("stripe_count: %d\nstripe_size: %d\n",
+ lum_file->lmm_stripe_count, lum_file->lmm_stripe_size);
+
+cleanup:
+ if (lum_file != NULL)
+ free(lum_file);
+ return rc;
+}
}
run_test 24a "FIEMAP upon PFL file"
+test_25() {
+ local pfl_f=$DIR/$tdir/"$tfile"_pfl
+ local dom_f=$DIR/$tdir/"$tfile"_dom
+ local common_f=$DIR/$tdir/"$tfile"_common
+ local stripe_count
+ local stripe_size
+
+ mkdir -p $DIR/$tdir || error "mkdir $DIR/$tdir failed"
+ $LFS setstripe -E 10M -S 64k -c -1 -E 20M -S 1M -E -1 -S 2M -c 1 \
+ $pfl_f || error "setstripe $pfl_f failed"
+ $LFS setstripe -E 256k -L mdt -E -1 -S 1M $dom_f ||
+ error "setstripe $dom_f failed"
+ $LFS setstripe -S 512K -c -1 $common_f ||
+ error "setstripe $common_f failed"
+
+ #verify lov_getstripe_old with PFL file
+ stripe_count=$(lov_getstripe_old $pfl_f |
+ awk '/stripe_count/ { print $2 }')
+ stripe_size=$(lov_getstripe_old $pfl_f |
+ awk '/stripe_size/ { print $2 }')
+ [ $stripe_count -eq 1 ] ||
+ error "stripe_count $stripe_count !=1 for $pfl_f"
+ [ $stripe_size -eq 2097152 ] ||
+ error "stripe_size $stripe_size != 2097152 for $pfl_f"
+
+ #verify lov_getstripe_old with DoM file
+ stripe_count=$(lov_getstripe_old $dom_f |
+ awk '/stripe_count/ { print $2 }')
+ stripe_size=$(lov_getstripe_old $dom_f |
+ awk '/stripe_size/ { print $2 }')
+ [ $stripe_count -eq 1 ] ||
+ error "stripe_count $stripe_count !=1 for $dom_f"
+ [ $stripe_size -eq 1048576 ] ||
+ error "stripe_size $stripe_size != 1048576 for $dom_f"
+
+ #verify lov_getstripe_old with common file
+ stripe_count=$(lov_getstripe_old $common_f |
+ awk '/stripe_count/ { print $2 }')
+ stripe_size=$(lov_getstripe_old $common_f |
+ awk '/stripe_size/ { print $2 }')
+ [ $stripe_count -eq $OSTCOUNT ] ||
+ error "stripe_count $stripe_count !=$OSTCOUNT for $common_f"
+ [ $stripe_size -eq 524288 ] ||
+ error "stripe_size $stripe_size != 524288 for $common_f"
+}
+run_test 25 "Verify old lov stripe API with PFL files"
+
complete $SECONDS
check_and_cleanup_lustre
exit_status