[[\fB!\fR] \fB--name\fR|\fB-n <\fIpattern\fR>]
[[\fB!\fR] \fB--ost\fR|\fB-O\fR <\fIindex\fR,...>]
[[\fB!\fR] \fB--pool\fR <\fIpool\fR>]
+[[\fB!\fR] \fB--foreign\fR [<\fItype\fR>]]
[\fB--print\fR|\fB-P\fR]
[\fB--print0\fR|\fB-0\fR]
[[\fB!\fR] \fB--projid\fR |<\fIprojid\fR>]
.I pool
name. For composite files, this may match the pool of any component.
.TP
+.BR --foreign[=<type>]
+Directory striping format is foreign (non-Lustre/free format) and is of type
+.BR <type>
+if specified. Presently only
+.BR none
+or
+.BR daos
+are defined types , though 32-bit numeric types can also be used.
+.TP
.BR --print | -P
Prints the file or directory name to standard output if it matches
all specified parameters, one file per line with a trailing linefeed.
Recursively list all out-of-sync mirrored files.
.TP
.B $ lfs find ! --foreign=daos /mnt/lustre
-Recursively list all but foreign files of daos type.
+Recursively list all but foreign files/dirs of
+.B daos
+type.
.SH BUGS
The
.B lfs find
.SH NAME
lfs setdirstripe, mkdir \- set striping pattern of a directory.
.SH SYNOPSIS
-.B lfs setdirstripe [\fR-cdDHioT\fR] \fIDIR\fR...
+.B lfs setdirstripe [\fR-cdDHioTx\fR] \fIDIR\fR...
.br
.SH DESCRIPTION
Create a striped directory with specified striping pattern. This lfs utility
is similar to
.BR lfs setstripe
, but is used to create striped directory.
+Can also be used to create directory with a foreign (free format) striping pattern (see
+.BR --foreign
+and
+.BR --xattr
+options).
.B lfs mkdir
is an alias for this command.
.SH OPTIONS
.BR chmod (1).
It is not affected by the current
.BR umask (1p).
+.TP
+.BR \-\-foreign[=type]
+Create a directory with a foreign (non-Lustre/free format, see
+.BR \-\-xattr
+option) striping. Where
+.BR type
+specifies a known foreign type (like
+.BR none
+,
+.BR daos
+, ...) or a 32-bit numeric type.
+.TP
+.BR \-\-flags =\fI<hex>\fR
+Specify a bitmask of flags.
+.TP
+.BR \-x ", " \-\-xattr =\fISTRING\fR
+Specify a string to be used as a foreign (free format) striping.
.SH NOTE
.PP
The
.B MDT0001
(MDT index 1), and whose hash type is
.BR all_char .
+.TP
+.B $ lfs mkdir --foreign=daos --xattr PUUID:CUUID /mnt/lustre/dir1
+This creates
+.B dir1
+with foreign (non-lustre/free format)
+.B PUUID:CUUID
+striping/LMV EA.
.SH AVAILABILITY
The
.B lfs setdirstripe
const char *pool_name);
int llapi_dir_create(const char *name, mode_t mode,
const struct llapi_stripe_param *param);
+int llapi_dir_create_foreign(const char *name, mode_t mode, __u32 type,
+ __u32 flags, const char *value);
int llapi_dir_create_pool(const char *name, int flags, int stripe_offset,
int stripe_count, int stripe_pattern,
const char *poolname);
(type & LMV_HASH_TYPE_MASK) == LMV_HASH_TYPE_ALL_CHARS;
}
+static inline bool lmv_magic_supported(__u32 lum_magic)
+{
+ return lum_magic == LMV_USER_MAGIC ||
+ lum_magic == LMV_USER_MAGIC_SPECIFIC ||
+ lum_magic == LMV_MAGIC_FOREIGN;
+}
+
#endif
struct lustre_md {
struct mdt_body *body;
struct lu_buf layout;
- struct lmv_stripe_md *lmv;
+ union {
+ struct lmv_stripe_md *lmv;
+ struct lmv_foreign_md *lfm;
+ };
#ifdef CONFIG_FS_POSIX_ACL
struct posix_acl *posix_acl;
#endif
struct lu_fid lmv_stripe_fids[0]; /* FIDs for each stripe */
};
+/* foreign LMV EA */
+struct lmv_foreign_md {
+ __u32 lfm_magic; /* magic number = LMV_MAGIC_FOREIGN */
+ __u32 lfm_length; /* length of lfm_value */
+ __u32 lfm_type; /* type, see LU_FOREIGN_TYPE_ */
+ __u32 lfm_flags; /* flags, type specific */
+ char lfm_value[]; /* free format value */
+};
+
#define LMV_MAGIC_V1 0x0CD20CD0 /* normal stripe lmv magic */
#define LMV_MAGIC LMV_MAGIC_V1
/* #define LMV_USER_MAGIC 0x0CD30CD0 */
#define LMV_MAGIC_STRIPE 0x0CD40CD0 /* magic for dir sub_stripe */
+#define LMV_MAGIC_FOREIGN 0x0CD50CD0 /* magic for lmv foreign */
/* Right now only the lower part(0-16bits) of lmv_hash_type is being used,
* and the higher part will be the flag to indicate the status of object,
__u32 lmv_magic;
struct lmv_mds_md_v1 lmv_md_v1;
struct lmv_user_md lmv_user_md;
+ struct lmv_foreign_md lmv_foreign_md;
};
static inline int lmv_mds_md_size(int stripe_count, unsigned int lmm_magic)
struct lov_foreign_md {
__u32 lfm_magic; /* magic number = LOV_MAGIC_FOREIGN */
__u32 lfm_length; /* length of lfm_value */
- __u32 lfm_type; /* type, see LOV_FOREIGN_TYPE_ */
+ __u32 lfm_type; /* type, see LU_FOREIGN_TYPE_ */
__u32 lfm_flags; /* flags, type specific */
char lfm_value[];
};
extern char *mdt_hash_name[LMV_HASH_TYPE_MAX];
-/**
- * LOV foreign types
- **/
-#define LOV_FOREIGN_TYPE_NONE 0
-#define LOV_FOREIGN_TYPE_DAOS 0xda05
-#define LOV_FOREIGN_TYPE_UNKNOWN UINT32_MAX
-
struct lustre_foreign_type {
uint32_t lft_type;
const char *lft_name;
};
-extern struct lustre_foreign_type lov_foreign_type[];
+/**
+ * LOV/LMV foreign types
+ **/
+enum lustre_foreign_types {
+ LU_FOREIGN_TYPE_NONE = 0,
+ LU_FOREIGN_TYPE_DAOS = 0xda05,
+ /* must be the max/last one */
+ LU_FOREIGN_TYPE_UNKNOWN = 0xffffffff,
+};
+
+extern struct lustre_foreign_type lu_foreign_types[];
/* Got this according to how get LOV_MAX_STRIPE_COUNT, see above,
* (max buffer size - lmv+rpc header) / sizeof(struct lmv_user_mds_data) */
struct lmv_user_mds_data lum_objects[0];
} __attribute__((packed));
+static inline __u32 lmv_foreign_to_md_stripes(__u32 size)
+{
+ if (size <= sizeof(struct lmv_user_md))
+ return 0;
+
+ size -= sizeof(struct lmv_user_md);
+ return (size + sizeof(struct lmv_user_mds_data) - 1) /
+ sizeof(struct lmv_user_mds_data);
+}
+
static inline int lmv_user_md_size(int stripes, int lmm_magic)
{
int size = sizeof(struct lmv_user_md);
struct lfsck_thread_info *info = lfsck_env_info(env);
struct lu_buf *buf = &info->lti_buf;
int size = sizeof(*lmv) + sizeof(struct lu_fid) * 2;
+ struct lmv_foreign_md *lfm;
int rc;
dt_read_lock(env, obj, 0);
rc = dt_xattr_get(env, obj, buf, XATTR_NAME_LMV);
if (unlikely(rc == -ERANGE)) {
buf = &info->lti_big_buf;
- lu_buf_check_and_alloc(buf, size);
- rc = dt_xattr_get(env, obj, buf, XATTR_NAME_LMV);
/* For the in-migration directory, its LMV EA contains
* not only the LMV header, but also the FIDs for both
- * source and target. So the LMV EA size is larger. */
- if (rc == size) {
- rc = sizeof(*lmv);
- memcpy(lmv, buf->lb_buf, rc);
+ * source and target. So the LMV EA size is larger.
+ * Or may be this is a foreign LMV */
+ rc = dt_xattr_get(env, obj, &LU_BUF_NULL, XATTR_NAME_LMV);
+ if (rc > sizeof(*lmv)) {
+ int rc1;
+
+ lu_buf_check_and_alloc(buf, rc);
+ rc1 = dt_xattr_get(env, obj, buf, XATTR_NAME_LMV);
+ if (rc != rc1)
+ rc = -EINVAL;
+ } else {
+ rc = -EINVAL;
}
}
dt_read_unlock(env, obj);
+
+ if (rc > 0 && rc > offsetof(typeof(*lfm), lfm_value) &&
+ *((__u32 *)buf->lb_buf) == LMV_MAGIC_FOREIGN) {
+ __u32 value_len;
+
+ lfm = buf->lb_buf;
+ value_len = le32_to_cpu(lfm->lfm_length);
+ CDEBUG(D_INFO,
+ "foreign LMV EA, magic %x, len %u, type %x, flags %x, for dir "DFID"\n",
+ le32_to_cpu(lfm->lfm_magic), value_len,
+ le32_to_cpu(lfm->lfm_type), le32_to_cpu(lfm->lfm_flags),
+ PFID(lfsck_dto2fid(obj)));
+
+ if (rc != value_len + offsetof(typeof(*lfm), lfm_value))
+ CDEBUG(D_LFSCK,
+ "foreign LMV EA internal size %u does not match EA full size %d for dir "DFID"\n",
+ value_len, rc, PFID(lfsck_dto2fid(obj)));
+
+ /* no further usage/decode of foreign LMV outside */
+ return -ENODATA;
+ }
+
+ if (rc == size) {
+ rc = sizeof(*lmv);
+ memcpy(lmv, buf->lb_buf, rc);
+ }
if (rc != sizeof(*lmv))
return rc > 0 ? -EINVAL : rc;
LUSTRE_OPC_ANY, inode);
if (IS_ERR(op_data))
GOTO(out, rc = PTR_ERR(op_data));
+
+ /* foreign dirs are browsed out of Lustre */
+ if (unlikely(op_data->op_mea1 != NULL &&
+ op_data->op_mea1->lsm_md_magic == LMV_MAGIC_FOREIGN)) {
+ ll_finish_md_op_data(op_data);
+ RETURN(-ENODATA);
+ }
+
op_data->op_fid3 = pfid;
#ifdef HAVE_DIR_CONTEXT
int err;
ENTRY;
- if (unlikely(lump->lum_magic != LMV_USER_MAGIC &&
- lump->lum_magic != LMV_USER_MAGIC_SPECIFIC))
+ if (unlikely(!lmv_magic_supported(lump->lum_magic)))
RETURN(-EINVAL);
- CDEBUG(D_VFSTRACE, "VFS Op:inode="DFID"(%p) name %s "
- "stripe_offset %d, stripe_count: %u\n",
- PFID(ll_inode2fid(parent)), parent, dirname,
- (int)lump->lum_stripe_offset, lump->lum_stripe_count);
+ if (lump->lum_magic != LMV_MAGIC_FOREIGN) {
+ CDEBUG(D_VFSTRACE,
+ "VFS Op:inode="DFID"(%p) name %s stripe_offset %d, stripe_count: %u\n",
+ PFID(ll_inode2fid(parent)), parent, dirname,
+ (int)lump->lum_stripe_offset, lump->lum_stripe_count);
+ } else {
+ struct lmv_foreign_md *lfm = (struct lmv_foreign_md *)lump;
+
+ CDEBUG(D_VFSTRACE,
+ "VFS Op:inode="DFID"(%p) name %s foreign, length %u, value '%.*s'\n",
+ PFID(ll_inode2fid(parent)), parent, dirname,
+ lfm->lfm_length, lfm->lfm_length, lfm->lfm_value);
+ }
if (lump->lum_stripe_count > 1 &&
!(exp_connect_flags(sbi->ll_md_exp) & OBD_CONNECT_DIR_STRIPE))
!OBD_FAIL_CHECK(OBD_FAIL_LLITE_NO_CHECK_DEAD))
RETURN(-ENOENT);
- if (lump->lum_magic != cpu_to_le32(LMV_USER_MAGIC) &&
- lump->lum_magic != cpu_to_le32(LMV_USER_MAGIC_SPECIFIC))
+ if (unlikely(!lmv_magic_supported(cpu_to_le32(lump->lum_magic))))
lustre_swab_lmv_user_md(lump);
if (!IS_POSIXACL(parent) || !exp_connect_umask(ll_i2mdexp(parent)))
}
}
break;
+ case LMV_MAGIC_FOREIGN: {
+ struct lmv_foreign_md *lfm = (struct lmv_foreign_md *)lmm;
+
+ if (LMV_MAGIC_FOREIGN != cpu_to_le32(LMV_MAGIC_FOREIGN)) {
+ __swab32s(&lfm->lfm_magic);
+ __swab32s(&lfm->lfm_length);
+ __swab32s(&lfm->lfm_type);
+ __swab32s(&lfm->lfm_flags);
+ }
+ break;
+ }
default:
CERROR("unknown magic: %lX\n", (unsigned long)lmm->lmm_magic);
rc = -EPROTO;
lum = (struct lmv_user_md *)data->ioc_inlbuf2;
lumlen = data->ioc_inllen2;
- if ((lum->lum_magic != LMV_USER_MAGIC &&
- lum->lum_magic != LMV_USER_MAGIC_SPECIFIC) ||
+ if (!lmv_magic_supported(lum->lum_magic)) {
+ CERROR("%s: wrong lum magic %x : rc = %d\n", filename,
+ lum->lum_magic, -EINVAL);
+ GOTO(lmv_out_free, rc = -EINVAL);
+ }
+
+ if ((lum->lum_magic == LMV_USER_MAGIC ||
+ lum->lum_magic == LMV_USER_MAGIC_SPECIFIC) &&
lumlen < sizeof(*lum)) {
+ CERROR("%s: wrong lum size %d for magic %x : rc = %d\n",
+ filename, lumlen, lum->lum_magic, -EINVAL);
+ GOTO(lmv_out_free, rc = -EINVAL);
+ }
+
+ if (lum->lum_magic == LMV_MAGIC_FOREIGN &&
+ lumlen < sizeof(struct lmv_foreign_md)) {
CERROR("%s: wrong lum magic %x or size %d: rc = %d\n",
filename, lum->lum_magic, lumlen, -EFAULT);
GOTO(lmv_out_free, rc = -EINVAL);
GOTO(finish_req, rc);
}
- stripe_count = lmv_mds_md_stripe_count_get(lmm);
+ /* if foreign LMV case, fake stripes number */
+ if (lmm->lmv_magic == LMV_MAGIC_FOREIGN) {
+ struct lmv_foreign_md *lfm;
+
+ lfm = (struct lmv_foreign_md *)lmm;
+ if (lfm->lfm_length < XATTR_SIZE_MAX -
+ offsetof(typeof(*lfm), lfm_value)) {
+ __u32 size = lfm->lfm_length +
+ offsetof(typeof(*lfm), lfm_value);
+
+ stripe_count = lmv_foreign_to_md_stripes(size);
+ } else {
+ CERROR("invalid %d foreign size returned\n",
+ lfm->lfm_length);
+ return -EINVAL;
+ }
+ } else {
+ stripe_count = lmv_mds_md_stripe_count_get(lmm);
+ }
if (max_stripe_count < stripe_count) {
lum.lum_stripe_count = stripe_count;
if (copy_to_user(ulmv, &lum, sizeof(lum)))
GOTO(finish_req, rc = -E2BIG);
}
+ /* enough room on user side and foreign case */
+ if (lmm->lmv_magic == LMV_MAGIC_FOREIGN) {
+ struct lmv_foreign_md *lfm;
+ __u32 size;
+
+ lfm = (struct lmv_foreign_md *)lmm;
+ size = lfm->lfm_length +
+ offsetof(struct lmv_foreign_md, lfm_value);
+ if (copy_to_user(ulmv, lfm, size))
+ GOTO(finish_req, rc = -EFAULT);
+ GOTO(finish_req, rc);
+ }
+
lum_size = lmv_user_md_size(stripe_count,
LMV_USER_MAGIC_SPECIFIC);
OBD_ALLOC(tmp, lum_size);
int rc;
LASSERT(lli->lli_lsm_md != NULL);
+
+ /* foreign dir is not striped dir */
+ if (lli->lli_lsm_md->lsm_md_magic == LMV_MAGIC_FOREIGN)
+ RETURN(0);
+
down_read(&lli->lli_lsm_sem);
rc = md_merge_attr(ll_i2mdexp(inode), ll_i2info(inode)->lli_lsm_md,
&attr, ll_md_blocking_ast);
/*
* if dir layout mismatch, check whether version is increased, which
* means layout is changed, this happens in dir migration and lfsck.
+ *
+ * foreign LMV should not change.
*/
- if (lli->lli_lsm_md && !lsm_md_eq(lli->lli_lsm_md, lsm)) {
+ if (lli->lli_lsm_md &&
+ lli->lli_lsm_md->lsm_md_magic != LMV_MAGIC_FOREIGN &&
+ !lsm_md_eq(lli->lli_lsm_md, lsm)) {
if (lsm->lsm_md_layout_version <=
lli->lli_lsm_md->lsm_md_layout_version) {
CERROR("%s: "DFID" dir layout mismatch:\n",
if (!lli->lli_lsm_md) {
struct cl_attr *attr;
+ if (lsm->lsm_md_magic == LMV_MAGIC_FOREIGN) {
+ /* set md->lmv to NULL, so the following free lustre_md
+ * will not free this lsm */
+ md->lmv = NULL;
+ lli->lli_lsm_md = lsm;
+ up_write(&lli->lli_lsm_sem);
+ RETURN(0);
+ }
+
rc = ll_init_lsm_md(inode, md);
up_write(&lli->lli_lsm_sem);
if (rc != 0)
rc = md_get_lustre_md(sbi->ll_md_exp, req, sbi->ll_dt_exp,
sbi->ll_md_exp, &md);
if (rc != 0)
- GOTO(cleanup, rc);
+ GOTO(out, rc);
if (*inode) {
rc = ll_update_inode(*inode, &md);
GOTO(out, rc = 0);
out:
+ /* cleanup will be done if necessary */
md_free_lustre_md(sbi->ll_md_exp, &md);
-cleanup:
if (rc != 0 && it != NULL && it->it_op & IT_OPEN)
ll_open_cleanup(sb != NULL ? sb : (*inode)->i_sb, req);
ENTRY;
+ /* do not allow file creation in foreign dir */
+ if ((it->it_op & IT_CREAT) && op_data->op_mea1 != NULL &&
+ op_data->op_mea1->lsm_md_magic == LMV_MAGIC_FOREIGN)
+ RETURN(-ENODATA);
+
if ((it->it_op & IT_CREAT) && !(flags & MDS_OPEN_BY_FID)) {
/* don't allow create under dir with bad hash */
if (lmv_is_dir_bad_hash(op_data->op_mea1))
int rc;
ENTRY;
+ /* foreign dir is not striped */
+ if (op_data->op_mea1 &&
+ op_data->op_mea1->lsm_md_magic == LMV_MAGIC_FOREIGN) {
+ /* only allow getattr/lookup for itself */
+ if (op_data->op_name != NULL)
+ RETURN(-ENODATA);
+ RETURN(0);
+ }
+
retry:
tgt = lmv_locate_tgt(lmv, op_data, &op_data->op_fid1);
if (IS_ERR(tgt))
* 1. See if the stripe offset is specified by lum.
* 2. Then check if there is default stripe offset.
* 3. Finally choose MDS by name hash if the parent
- * is striped directory. (see lmv_locate_tgt()). */
+ * is striped directory. (see lmv_locate_tgt()).
+ *
+ * presently explicit MDT location is not supported
+ * for foreign dirs (as it can't be embedded into free
+ * format LMV, like with lum_stripe_offset), so we only
+ * rely on default stripe offset or then name hashing.
+ */
if (op_data->op_cli_flags & CLI_SET_MEA && lum != NULL &&
+ le32_to_cpu(lum->lum_magic != LMV_MAGIC_FOREIGN) &&
le32_to_cpu(lum->lum_stripe_offset) != (__u32)-1) {
*mds = le32_to_cpu(lum->lum_stripe_offset);
} else if (op_data->op_default_stripe_offset != (__u32)-1) {
*mds = op_data->op_default_stripe_offset;
op_data->op_mds = *mds;
/* Correct the stripe offset in lum */
- if (lum != NULL)
+ if (lum != NULL &&
+ le32_to_cpu(lum->lum_magic != LMV_MAGIC_FOREIGN))
lum->lum_stripe_offset = cpu_to_le32(*mds);
} else {
*mds = op_data->op_mds;
struct lmv_oinfo *oinfo;
struct lmv_tgt_desc *tgt;
+ /* foreign dir is not striped dir */
+ if (lsm && lsm->lsm_md_magic == LMV_MAGIC_FOREIGN)
+ return ERR_PTR(-ENODATA);
+
/* During creating VOLATILE file, it should honor the mdt
* index if the file under striped dir is being restored, see
* ct_restore(). */
ENTRY;
if (unlikely(lsm != NULL)) {
+ /* foreign dir is not striped dir */
+ if (lsm->lsm_md_magic == LMV_MAGIC_FOREIGN)
+ return -ENODATA;
+
rc = lmv_striped_read_page(exp, op_data, cb_op, offset, ppage);
RETURN(rc);
}
/* Free memmd */
if (lsm != NULL && lmm == NULL) {
int i;
+ struct lmv_foreign_md *lfm = (struct lmv_foreign_md *)lsm;
+
+ if (lfm->lfm_magic == LMV_MAGIC_FOREIGN) {
+ size_t lfm_size;
+
+ lfm_size = lfm->lfm_length + offsetof(typeof(*lfm),
+ lfm_value[0]);
+ OBD_FREE_LARGE(lfm, lfm_size);
+ RETURN(0);
+ }
for (i = 0; i < lsm->lsm_md_stripe_count; i++)
iput(lsm->lsm_md_oinfo[i].lmo_root);
RETURN(0);
}
+ /* foreign lmv case */
+ if (le32_to_cpu(lmm->lmv_magic) == LMV_MAGIC_FOREIGN) {
+ struct lmv_foreign_md *lfm = (struct lmv_foreign_md *)lsm;
+
+ if (lfm == NULL) {
+ OBD_ALLOC_LARGE(lfm, lmm_size);
+ if (lfm == NULL)
+ RETURN(-ENOMEM);
+ *lsmp = (struct lmv_stripe_md *)lfm;
+ }
+ lfm->lfm_magic = le32_to_cpu(lmm->lmv_foreign_md.lfm_magic);
+ lfm->lfm_length = le32_to_cpu(lmm->lmv_foreign_md.lfm_length);
+ lfm->lfm_type = le32_to_cpu(lmm->lmv_foreign_md.lfm_type);
+ lfm->lfm_flags = le32_to_cpu(lmm->lmv_foreign_md.lfm_flags);
+ memcpy(&lfm->lfm_value, &lmm->lmv_foreign_md.lfm_value,
+ lfm->lfm_length);
+ RETURN(lmm_size);
+ }
+
if (le32_to_cpu(lmm->lmv_magic) == LMV_MAGIC_STRIPE)
RETURN(-EPERM);
int rc;
int i;
+ /* foreign dir is not striped dir */
+ if (lsm->lsm_md_magic == LMV_MAGIC_FOREIGN)
+ return 0;
+
rc = lmv_revalidate_slaves(exp, lsm, cb_blocking, 0);
if (rc < 0)
return rc;
__u32 ldo_dir_slave_stripe:1,
ldo_dir_striped:1,
/* the stripe has been loaded */
- ldo_dir_stripe_loaded:1;
+ ldo_dir_stripe_loaded:1,
+ /* foreign directory */
+ ldo_dir_is_foreign;
/*
* default striping is not cached, so this field is
* invalid after create, make sure it's used by
size_t ldo_foreign_lov_size;
};
struct {
+ /* foreign/raw format LMV */
+ char *ldo_foreign_lmv;
+ size_t ldo_foreign_lmv_size;
+ };
+ struct {
/* file stripe (LOV) */
struct lod_layout_component *ldo_comp_entries;
/* slave stripes of striped directory (LMV) */
lo->ldo_comp_cached = 1;
} else if (S_ISDIR(lod2lu_obj(lo)->lo_header->loh_attr)) {
rc = lod_get_lmv_ea(env, lo);
+ if (rc > sizeof(struct lmv_foreign_md)) {
+ struct lmv_foreign_md *lfm = info->lti_ea_store;
+
+ if (le32_to_cpu(lfm->lfm_magic) == LMV_MAGIC_FOREIGN) {
+ lo->ldo_foreign_lmv = info->lti_ea_store;
+ lo->ldo_foreign_lmv_size =
+ info->lti_ea_store_size;
+ info->lti_ea_store = NULL;
+ info->lti_ea_store_size = 0;
+
+ lo->ldo_dir_stripe_loaded = 1;
+ lo->ldo_dir_is_foreign = 1;
+ GOTO(unlock, rc = 0);
+ }
+ }
+
if (rc < (typeof(rc))sizeof(struct lmv_mds_md_v1)) {
/* Let's set stripe_loaded to avoid further
* stripe loading especially for non-stripe directory,
rc = dt_xattr_get(env, dt_object_child(dt), buf, name);
if (strcmp(name, XATTR_NAME_LMV) == 0) {
struct lmv_mds_md_v1 *lmv1;
+ struct lmv_foreign_md *lfm;
int rc1 = 0;
if (rc > (typeof(rc))sizeof(*lmv1))
RETURN(rc);
- if (rc < (typeof(rc))sizeof(*lmv1))
+ /* short (<= sizeof(struct lmv_mds_md_v1)) foreign LMV case */
+ /* XXX empty foreign LMV is not allowed */
+ if (rc <= offsetof(typeof(*lfm), lfm_value))
RETURN(rc = rc > 0 ? -EINVAL : rc);
if (buf->lb_buf == NULL || buf->lb_len == 0) {
CLASSERT(sizeof(*lmv1) <= sizeof(info->lti_key));
+ /* lti_buf is large enough for *lmv1 or a short
+ * (<= sizeof(struct lmv_mds_md_v1)) foreign LMV
+ */
info->lti_buf.lb_buf = info->lti_key;
info->lti_buf.lb_len = sizeof(*lmv1);
rc = dt_xattr_get(env, dt_object_child(dt),
&info->lti_buf, name);
+ if (unlikely(rc <= offsetof(typeof(*lfm),
+ lfm_value)))
+ RETURN(rc = rc > 0 ? -EINVAL : rc);
+
+ lfm = info->lti_buf.lb_buf;
+ if (le32_to_cpu(lfm->lfm_magic) == LMV_MAGIC_FOREIGN)
+ RETURN(rc);
+
if (unlikely(rc != sizeof(*lmv1)))
RETURN(rc = rc > 0 ? -EINVAL : rc);
le32_to_cpu(lmv1->lmv_stripe_count),
LMV_MAGIC_V1);
} else {
+ lfm = buf->lb_buf;
+ if (le32_to_cpu(lfm->lfm_magic) == LMV_MAGIC_FOREIGN)
+ RETURN(rc);
+
+ if (rc != sizeof(*lmv1))
+ RETURN(rc = rc > 0 ? -EINVAL : rc);
+
rc1 = lod_load_lmv_shards(env, lod_dt_obj(dt),
buf, false);
}
LASSERT(mutex_is_locked(&lo->ldo_layout_mutex));
+ /* XXX may be useless as not called for foreign LMV ?? */
+ if (le32_to_cpu(lmv1->lmv_magic) == LMV_MAGIC_FOREIGN)
+ RETURN(0);
+
if (le32_to_cpu(lmv1->lmv_magic) == LMV_MAGIC_STRIPE) {
lo->ldo_dir_slave_stripe = 1;
RETURN(0);
}
/**
+ *
+ * Alloc cached foreign LMV
+ *
+ * \param[in] lo object
+ * \param[in] size size of foreign LMV
+ *
+ * \retval 0 on success
+ * \retval negative if failed
+ */
+int lod_alloc_foreign_lmv(struct lod_object *lo, size_t size)
+{
+ OBD_ALLOC_LARGE(lo->ldo_foreign_lmv, size);
+ if (lo->ldo_foreign_lmv == NULL)
+ return -ENOMEM;
+ lo->ldo_foreign_lmv_size = size;
+ lo->ldo_dir_is_foreign = 1;
+
+ return 0;
+}
+
+/**
* Declare create striped md object.
*
* The function declares intention to create a striped directory. This is a
le32_to_cpu(lum->lum_magic), le32_to_cpu(lum->lum_stripe_count),
(int)le32_to_cpu(lum->lum_stripe_offset));
- if (lo->ldo_dir_stripe_count == 0)
+ if (lo->ldo_dir_stripe_count == 0) {
+ if (lo->ldo_dir_is_foreign) {
+ rc = lod_alloc_foreign_lmv(lo, lum_buf->lb_len);
+ if (rc != 0)
+ GOTO(out, rc);
+ memcpy(lo->ldo_foreign_lmv, lum, lum_buf->lb_len);
+ lo->ldo_dir_stripe_loaded = 1;
+ }
GOTO(out, rc = 0);
+ }
/* prepare dir striped objects */
rc = lod_prep_md_striped_create(env, dt, attr, lum, dof, th);
/* The stripes are supposed to be allocated in declare phase,
* if there are no stripes being allocated, it will skip */
- if (lo->ldo_dir_stripe_count == 0)
+ if (lo->ldo_dir_stripe_count == 0) {
+ if (lo->ldo_dir_is_foreign) {
+ rc = lod_sub_xattr_set(env, dt_object_child(dt), buf,
+ XATTR_NAME_LMV, fl, th);
+ if (rc != 0)
+ RETURN(rc);
+ }
RETURN(0);
+ }
rc = dt_attr_get(env, dt_object_child(dt), attr);
if (rc != 0)
th);
if (rc != 0)
RETURN(rc);
+ } else {
+ /* foreign LMV EA case */
+ if (lmu) {
+ struct lmv_foreign_md *lfm = lmu->lb_buf;
+
+ if (lfm->lfm_magic == LMV_MAGIC_FOREIGN) {
+ rc = lod_declare_xattr_set_lmv(env, dt, attr,
+ lmu, dof, th);
+ }
+ } else {
+ if (lo->ldo_dir_is_foreign) {
+ LASSERT(lo->ldo_foreign_lmv != NULL &&
+ lo->ldo_foreign_lmv_size > 0);
+ info->lti_buf.lb_buf = lo->ldo_foreign_lmv;
+ info->lti_buf.lb_len = lo->ldo_foreign_lmv_size;
+ lmu = &info->lti_buf;
+ rc = lod_xattr_set_lmv(env, dt, lmu,
+ XATTR_NAME_LMV, 0, th);
+ }
+ }
}
/* Transfer default LMV striping from the parent */
/* other default values are 0 */
lc->ldo_dir_stripe_offset = -1;
+ /* no default striping configuration is needed for
+ * foreign dirs
+ */
+ if (ah->dah_eadata != NULL && ah->dah_eadata_len != 0 &&
+ le32_to_cpu(lum1->lum_magic) == LMV_MAGIC_FOREIGN) {
+ lc->ldo_dir_is_foreign = true;
+ /* keep stripe_count 0 and stripe_offset -1 */
+ CDEBUG(D_INFO, "no default striping for foreign dir\n");
+ RETURN_EXIT;
+ }
+
/*
* If parent object is not root directory,
* then get default striping from parent object.
/**
*
+ * Free cached foreign LMV
+ *
+ * \param[in] lo object
+ */
+void lod_free_foreign_lmv(struct lod_object *lo)
+{
+ if (lo->ldo_foreign_lmv != NULL)
+ OBD_FREE_LARGE(lo->ldo_foreign_lmv, lo->ldo_foreign_lmv_size);
+ lo->ldo_foreign_lmv = NULL;
+ lo->ldo_foreign_lmv_size = 0;
+ lo->ldo_dir_is_foreign = 0;
+}
+
+/**
+ *
* Release resources associated with striping.
*
* If the object is striped (regular or directory), then release
if (unlikely(lo->ldo_is_foreign)) {
lod_free_foreign_lov(lo);
lo->ldo_comp_cached = 0;
+ } else if (unlikely(lo->ldo_dir_is_foreign)) {
+ lod_free_foreign_lmv(lo);
+ lo->ldo_dir_stripe_loaded = 0;
} else if (lo->ldo_stripe != NULL) {
LASSERT(lo->ldo_comp_entries == NULL);
LASSERT(lo->ldo_dir_stripes_allocated > 0);
GOTO(out, rc);
if (rc < (typeof(rc))sizeof(*md->lmv)) {
- CDEBUG(D_INFO, "size too small: "
- "rc < sizeof(*md->lmv) (%d < %d)\n",
- rc, (int)sizeof(*md->lmv));
- GOTO(out, rc = -EPROTO);
+ struct lmv_foreign_md *lfm = md->lfm;
+
+ /* short (< sizeof(struct lmv_stripe_md))
+ * foreign LMV case
+ */
+ if (lfm->lfm_magic != LMV_MAGIC_FOREIGN) {
+ CDEBUG(D_INFO,
+ "size too small: rc < sizeof(*md->lmv) (%d < %d)\n",
+ rc, (int)sizeof(*md->lmv));
+ GOTO(out, rc = -EPROTO);
+ }
}
}
}
spec->u.sp_ea.eadata != NULL && spec->u.sp_ea.eadatalen > 0) {
const struct lmv_user_md *lum = spec->u.sp_ea.eadata;
- if (le32_to_cpu(lum->lum_magic) != LMV_USER_MAGIC &&
- le32_to_cpu(lum->lum_magic) != LMV_USER_MAGIC_SPECIFIC &&
+ if (!lmv_magic_supported(le32_to_cpu(lum->lum_magic)) &&
le32_to_cpu(lum->lum_magic) != LMV_USER_MAGIC_V0) {
rc = -EINVAL;
CERROR("%s: invalid lmv_user_md: magic = %x, "
void mdt_dump_lmv(unsigned int level, const union lmv_mds_md *lmv)
{
const struct lmv_mds_md_v1 *lmm1;
+ const struct lmv_foreign_md *lfm;
int i;
if (likely(!cfs_cdebug_show(level, DEBUG_SUBSYSTEM)))
return;
+ /* foreign LMV case */
+ lfm = &lmv->lmv_foreign_md;
+ if (le32_to_cpu(lfm->lfm_magic) == LMV_MAGIC_FOREIGN) {
+ CDEBUG_LIMIT(level,
+ "foreign magic 0x%08X, length %u, type %u, flags %u, value '%.*s'\n",
+ le32_to_cpu(lfm->lfm_magic),
+ le32_to_cpu(lfm->lfm_length),
+ le32_to_cpu(lfm->lfm_type),
+ le32_to_cpu(lfm->lfm_flags),
+ le32_to_cpu(lfm->lfm_length), lfm->lfm_value);
+ return;
+ }
+
lmm1 = &lmv->lmv_md_v1;
CDEBUG(level,
"magic 0x%08X, master %#X stripe_count %#x hash_type %#x\n",
void lustre_swab_lmv_user_md(struct lmv_user_md *lum)
{
- __u32 count = lum->lum_stripe_count;
+ __u32 count;
+ if (lum->lum_magic == LMV_MAGIC_FOREIGN) {
+ __swab32s(&lum->lum_magic);
+ __swab32s(&((struct lmv_foreign_md *)lum)->lfm_length);
+ return;
+ }
+
+ count = lum->lum_stripe_count;
__swab32s(&lum->lum_magic);
__swab32s(&lum->lum_stripe_count);
__swab32s(&lum->lum_stripe_offset);
THETESTS += group_lock_test llapi_fid_test sendfile_grouplock mmap_cat
THETESTS += swap_lock_test lockahead_test mirror_io mmap_mknod_test
THETESTS += create_foreign_file parse_foreign_file
+THETESTS += create_foreign_dir parse_foreign_dir
if TESTS
if MPITESTS
mirror_io_LDADD = $(LIBLUSTREAPI)
ll_dirstripe_verify_LDADD = $(LIBLUSTREAPI)
flocks_test_LDADD = $(LIBLUSTREAPI) $(PTHREAD_LIBS)
+create_foreign_dir_LDADD = $(LIBLUSTREAPI)
endif # TESTS
--- /dev/null
+#include <stdlib.h>
+#include <unistd.h>
+#include <limits.h>
+#include <stdio.h>
+#include <errno.h>
+#include <libgen.h>
+#include <sys/ioctl.h>
+#include <sys/xattr.h>
+#include <sys/file.h>
+
+#include <lustre/lustreapi.h>
+
+int main(int argc, char **argv)
+{
+ char *dir = "foreign_dir", *end;
+ char *xval = "UUID@UUID";
+ mode_t mode = 0700;
+ __u32 type = LU_FOREIGN_TYPE_DAOS, flags = 0;
+ int c, rc;
+
+ while ((c = getopt(argc, argv, "hd:f:m:t:x:")) != -1) {
+ switch (c) {
+ case 'd':
+ dir = optarg;
+ break;
+ case 'x':
+ xval = optarg;
+ break;
+ case 'm':
+ mode = strtoul(optarg, &end, 8);
+ if (*end != '\0') {
+ fprintf(stderr,
+ "%s: invalid mode '%s'\n", argv[0],
+ optarg);
+ exit(1);
+ }
+ break;
+ case 'f':
+ flags = strtoul(optarg, &end, 0);
+ if (*end != '\0') {
+ fprintf(stderr,
+ "%s: invalid flags '%s'\n", argv[0],
+ optarg);
+ exit(1);
+ }
+ break;
+ case 't':
+ type = strtoul(optarg, &end, 0);
+ if (*end != '\0') {
+ fprintf(stderr,
+ "%s: invalid type '%s'\n", argv[0],
+ optarg);
+ exit(1);
+ }
+ break;
+ case 'h':
+ default:
+ fprintf(stderr,
+ "Usage: %s [-d <dirname>] [-m <octalmode>] [-x <LOV EA content>] [-t <type>] [-f <hexflags>]\n",
+ argv[0]);
+ exit(0);
+ break;
+ }
+ }
+
+ rc = llapi_dir_create_foreign(dir, mode, type, flags, xval);
+ if (rc < 0)
+ fprintf(stderr, "llapi_dir_create_foreign() error : %d\n", rc);
+
+ return rc;
+}
size_t len;
struct lov_foreign_md *lfm;
char *end;
- __u32 type = LOV_FOREIGN_TYPE_DAOS, flags = 0xda08;
+ __u32 type = LU_FOREIGN_TYPE_DAOS, flags = 0xda08;
while ((c = getopt(argc, argv, "f:x:t:F:")) != -1) {
switch (c) {
--- /dev/null
+#include <stdlib.h>
+#include <unistd.h>
+#include <limits.h>
+#include <stdio.h>
+#include <errno.h>
+#include <sys/ioctl.h>
+#include <sys/xattr.h>
+#include <sys/file.h>
+#include <sys/types.h>
+#include <sys/xattr.h>
+#include <byteswap.h>
+
+#include <linux/lustre/lustre_idl.h>
+
+int main(int argc, char **argv)
+{
+ int c, i;
+ char *dname = "DIR";
+ size_t len, len2;
+ struct lmv_foreign_md *lfm;
+
+ while ((c = getopt(argc, argv, "d:")) != -1) {
+ switch (c) {
+ case 'd':
+ dname = optarg;
+ break;
+ case 'h':
+ fprintf(stderr, "Usage: %s -d <dirname>\n", argv[0]);
+ break;
+ }
+ }
+
+ len = getxattr(dname, "trusted.lmv", NULL, 0);
+ if (len == -1) {
+ perror("getxattr()");
+ exit(1);
+ }
+ if (len > XATTR_SIZE_MAX || len <= 0) {
+ fprintf(stderr, "invalid LMV EA length %zu "
+ "(must be 0 < len < "
+ "XATTR_SIZE_MAX(%u))\n", len,
+ XATTR_SIZE_MAX);
+ exit(1);
+ }
+
+ lfm = malloc(len);
+ if (lfm == NULL) {
+ perror("malloc()");
+ exit(1);
+ }
+
+ len2 = getxattr(dname, "trusted.lmv", lfm, len);
+ if (len2 == -1) {
+ perror("getxattr()");
+ exit(1);
+ }
+
+ if (len != len2)
+ fprintf(stderr, "trusted.lmv xattr size changed, before=%zu "
+ "now=%zu\n", len, len2);
+
+ if (len2 < offsetof(struct lmv_foreign_md, lfm_value)) {
+ fprintf(stderr, "trusted.lov size=%zu too small\n", len2);
+ fprintf(stderr, "printing its content in hex anyway :\n");
+ for (i = 0; i < len2; i++)
+ fprintf(stderr, "%02x", *((char *)lfm + i));
+ exit(1);
+ }
+
+
+ if (lfm->lfm_magic != LMV_MAGIC_FOREIGN) {
+ if (lfm->lfm_magic == bswap_32(LMV_MAGIC_FOREIGN))
+ fprintf(stderr, "magic is swapped\n");
+ else
+ fprintf(stderr, "wrong magic=(0x%x)\n", lfm->lfm_magic);
+ }
+
+ if (lfm->lfm_length != len2 - offsetof(typeof(*lfm), lfm_value)) {
+ if (bswap_32(lfm->lfm_length) == len2 - offsetof(typeof(*lfm),
+ lfm_value))
+ fprintf(stderr, "length is swapped\n");
+ else
+ fprintf(stderr, "wrong internal length=%u(0x%x) vs "
+ "xattr size=%zu\n", lfm->lfm_length,
+ lfm->lfm_length, len2);
+ }
+
+ fprintf(stdout, "lmv_xattr_size: %zu\n", len2);
+ fprintf(stdout, "lmv_foreign_magic: 0x%x\n", lfm->lfm_magic);
+ fprintf(stdout, "lmv_foreign_size: %u\n", lfm->lfm_length);
+ fprintf(stdout, "lmv_foreign_type: %u\n", lfm->lfm_type);
+ fprintf(stdout, "lmv_foreign_flags: %u\n", lfm->lfm_flags);
+ fprintf(stdout, "lmv_foreign_value: 0x");
+ for (i = 0; i < len2 - offsetof(typeof(*lfm), lfm_value); i++)
+ fprintf(stdout, "%02x", lfm->lfm_value[i]);
+
+ fprintf(stdout, "\n");
+
+ return 0;
+}
}
run_test 38 "LFSCK does not break foreign file and reverse is also true"
+test_39()
+{
+ [[ $(lustre_version_code $SINGLEMDS) -le $(version_code 2.12.51) ]] &&
+ skip "Need MDS version newer than 2.12.51"
+
+ test_mkdir $DIR/$tdir
+ local uuid1=$(cat /proc/sys/kernel/random/uuid)
+ local uuid2=$(cat /proc/sys/kernel/random/uuid)
+
+ # create foreign dir
+ $LFS mkdir --foreign=daos --xattr="${uuid1}@${uuid2}" --flags=0xda05 \
+ $DIR/$tdir/${tdir}2 ||
+ error "$DIR/$tdir/${tdir}2: create failed"
+
+ $LFS getdirstripe -v $DIR/$tdir/${tdir}2 |
+ grep "lfm_magic:.*0x0CD50CD0" ||
+ error "$DIR/$tdir/${tdir}2: invalid LMV EA magic"
+ # lfm_length is LMV EA size - sizeof(lfm_magic) - sizeof(lfm_length)
+ # - sizeof(lfm_type) - sizeof(lfm_flags)
+ $LFS getdirstripe -v $DIR/$tdir/${tdir}2 | grep "lfm_length:.*73" ||
+ error "$DIR/$tdir/${tdir}2: invalid LMV EA size"
+ $LFS getdirstripe -v $DIR/$tdir/${tdir}2 | grep "lfm_type:.*daos" ||
+ error "$DIR/$tdir/${tdir}2: invalid LMV EA type"
+ $LFS getdirstripe -v $DIR/$tdir/${tdir}2 |
+ grep "lfm_flags:.*0x0000DA05" ||
+ error "$DIR/$tdir/${tdir}2: invalid LMV EA flags"
+ $LFS getdirstripe $DIR/$tdir/${tdir}2 |
+ grep "lfm_value.*${uuid1}@${uuid2}" ||
+ error "$DIR/$tdir/${tdir}2: invalid LMV EA value"
+
+ # file create in dir should fail
+ touch $DIR/$tdir/${tdir}2/$tfile &&
+ "$DIR/${tdir}2: file create should fail"
+
+ # chmod should work
+ chmod 777 $DIR/$tdir/${tdir}2 ||
+ error "$DIR/${tdir}2: chmod failed"
+
+ # chown should work
+ chown $RUNAS_ID:$RUNAS_GID $DIR/$tdir/${tdir}2 ||
+ error "$DIR/${tdir}2: chown failed"
+
+ $START_NAMESPACE -r -A || error "Fail to start LFSCK for namespace"
+
+ wait_all_targets_blocked namespace completed 1
+
+ # check that "global" namespace_repaired == 0 !!!
+ local repaired=$(do_facet mds1 \
+ "$LCTL lfsck_query -t all -M ${FSNAME}-MDT0000 |
+ awk '/^namespace_repaired/ { print \\\$2 }'")
+ [ $repaired -eq 0 ] ||
+ error "(2) Expect nothing to be repaired, but got: $repaired"
+
+ $START_LAYOUT -A -r || error "Fail to start LFSCK for layout"
+
+ wait_all_targets_blocked layout completed 2
+
+ # check that "global" layout_repaired == 0 !!!
+ local repaired=$(do_facet mds1 \
+ "$LCTL lfsck_query -t all -M ${FSNAME}-MDT0000 |
+ awk '/^layout_repaired/ { print \\\$2 }'")
+ [ $repaired -eq 0 ] ||
+ error "(2) Expect no layout repair, but got: $repaired"
+
+ echo "post-lfsck checks of foreign dir"
+
+ $LFS getdirstripe -v $DIR/$tdir/${tdir}2 |
+ grep "lfm_magic:.*0x0CD50CD0" ||
+ error "$DIR/$tdir/${tdir}2: invalid LMV EA magic"
+ # lfm_length is LMV EA size - sizeof(lfm_magic) - sizeof(lfm_length)
+ # - sizeof(lfm_type) - sizeof(lfm_flags)
+ $LFS getdirstripe -v $DIR/$tdir/${tdir}2 | grep "lfm_length:.*73" ||
+ error "$DIR/$tdir/${tdir}2: invalid LMV EA size"
+ $LFS getdirstripe -v $DIR/$tdir/${tdir}2 | grep "lfm_type:.*daos" ||
+ error "$DIR/$tdir/${tdir}2: invalid LMV EA type"
+ $LFS getdirstripe -v $DIR/$tdir/${tdir}2 |
+ grep "lfm_flags:.*0x0000DA05" ||
+ error "$DIR/$tdir/${tdir}2: invalid LMV EA flags"
+ $LFS getdirstripe $DIR/$tdir/${tdir}2 |
+ grep "lfm_value.*${uuid1}@${uuid2}" ||
+ error "$DIR/$tdir/${tdir}2: invalid LMV EA value"
+
+ # file create in dir should fail
+ touch $DIR/$tdir/${tdir}2/$tfile &&
+ "$DIR/${tdir}2: file create should fail"
+
+ # chmod should work
+ chmod 777 $DIR/$tdir/${tdir}2 ||
+ error "$DIR/${tdir}2: chmod failed"
+
+ # chown should work
+ chown $RUNAS_ID:$RUNAS_GID $DIR/$tdir/${tdir}2 ||
+ error "$DIR/${tdir}2: chown failed"
+
+ #remove foreign dir
+ rmdir $DIR/$tdir/${tdir}2 ||
+ error "$DIR/$tdir/${tdir}2: remove of foreign dir has failed"
+}
+run_test 39 "LFSCK does not break foreign dir and reverse is also true"
+
# restore MDS/OST size
MDSSIZE=${SAVED_MDSSIZE}
OSTSIZE=${SAVED_OSTSIZE}
$LFS getstripe -v $DIR/$tdir/${tfile}2 |
grep "lfm_flags:.*0x0000DA08" ||
error "$DIR/$tdir/${tfile}2: invalid LOV EA foreign flags"
- $LFS getstripe -v $DIR/$tdir/${tfile}2 |
+ $LFS getstripe $DIR/$tdir/${tfile}2 |
grep "lfm_value:.*${uuid1}@${uuid2}" ||
error "$DIR/$tdir/${tfile}2: invalid LOV EA foreign value"
}
run_test 27J "basic ops on file with foreign LOV"
+test_27K() {
+ [[ $(lustre_version_code $SINGLEMDS) -le $(version_code 2.12.49) ]] &&
+ skip "Need MDS version newer than 2.12.49"
+
+ test_mkdir $DIR/$tdir
+ local uuid1=$(cat /proc/sys/kernel/random/uuid)
+ local uuid2=$(cat /proc/sys/kernel/random/uuid)
+
+ # create foreign dir (raw way)
+ create_foreign_dir -d $DIR/$tdir/$tdir -x "${uuid1}@${uuid2}" -t 1 ||
+ error "create_foreign_dir FAILED"
+
+ # verify foreign dir (raw way)
+ parse_foreign_dir -d $DIR/$tdir/$tdir |
+ grep "lmv_foreign_magic:.*0xcd50cd0" ||
+ error "$DIR/$tdir/$tfile: invalid LMV EA magic"
+ parse_foreign_dir -d $DIR/$tdir/$tdir | grep "lmv_xattr_size:.*89$" ||
+ error "$DIR/$tdir/$tdir: invalid LMV EA size"
+ parse_foreign_dir -d $DIR/$tdir/$tdir | grep "lmv_foreign_type: 1$" ||
+ error "$DIR/$tdir/$tdir: invalid LMV EA type"
+ parse_foreign_dir -d $DIR/$tdir/$tdir | grep "lmv_foreign_flags: 0$" ||
+ error "$DIR/$tdir/$tdir: invalid LMV EA flags"
+ local lmv=$(parse_foreign_dir -d $DIR/$tdir/$tdir |
+ grep "lmv_foreign_value: 0x" |
+ sed 's/lmv_foreign_value: 0x//')
+ local lmv2=$(echo -n "${uuid1}@${uuid2}" | od -A n -t x1 -w160 |
+ sed 's/ //g')
+ [[ $lmv == $lmv2 ]] || error "$DIR/$tdir/$tdir: invalid LMV EA value"
+
+ # create foreign dir (lfs + API)
+ $LFS mkdir --foreign=daos --xattr="${uuid1}@${uuid2}" --flags=0xda05 \
+ $DIR/$tdir/${tdir}2 ||
+ error "$DIR/$tdir/${tdir}2: create failed"
+
+ $LFS getdirstripe -v $DIR/$tdir/${tdir}2 |
+ grep "lfm_magic:.*0x0CD50CD0" ||
+ error "$DIR/$tdir/${tdir}2: invalid LMV EA magic"
+ # lfm_length is LMV EA size - sizeof(lfm_magic) - sizeof(lfm_length)
+ # - sizeof(lfm_type) - sizeof(lfm_flags)
+ $LFS getdirstripe -v $DIR/$tdir/${tdir}2 | grep "lfm_length:.*73" ||
+ error "$DIR/$tdir/${tdir}2: invalid LMV EA size"
+ $LFS getdirstripe -v $DIR/$tdir/${tdir}2 | grep "lfm_type:.*daos" ||
+ error "$DIR/$tdir/${tdir}2: invalid LMV EA type"
+ $LFS getdirstripe -v $DIR/$tdir/${tdir}2 |
+ grep "lfm_flags:.*0x0000DA05" ||
+ error "$DIR/$tdir/${tdir}2: invalid LMV EA flags"
+ $LFS getdirstripe $DIR/$tdir/${tdir}2 |
+ grep "lfm_value.*${uuid1}@${uuid2}" ||
+ error "$DIR/$tdir/${tdir}2: invalid LMV EA value"
+
+ # file create in dir should fail
+ touch $DIR/$tdir/$tdir/$tfile && "$DIR/$tdir: file create should fail"
+ touch $DIR/$tdir/${tdir}2/$tfile &&
+ "$DIR/${tdir}2: file create should fail"
+
+ # chmod should work
+ chmod 777 $DIR/$tdir/$tdir ||
+ error "$DIR/$tdir: chmod failed"
+ chmod 777 $DIR/$tdir/${tdir}2 ||
+ error "$DIR/${tdir}2: chmod failed"
+
+ # chown should work
+ chown $RUNAS_ID:$RUNAS_GID $DIR/$tdir/$tdir ||
+ error "$DIR/$tdir: chown failed"
+ chown $RUNAS_ID:$RUNAS_GID $DIR/$tdir/${tdir}2 ||
+ error "$DIR/${tdir}2: chown failed"
+
+ # rename should work
+ mv $DIR/$tdir/$tdir $DIR/$tdir/${tdir}.new ||
+ error "$DIR/$tdir/$tdir: rename of foreign dir has failed"
+ mv $DIR/$tdir/${tdir}2 $DIR/$tdir/${tdir}2.new ||
+ error "$DIR/$tdir/${tdir}2: rename of foreign dir has failed"
+
+ #remove foreign dir
+ rmdir $DIR/$tdir/${tdir}.new ||
+ error "$DIR/$tdir/${tdir}.new: remove of foreign dir has failed"
+ rmdir $DIR/$tdir/${tdir}2.new ||
+ error "$DIR/$tdir/${tdir}2.new: remove of foreign dir has failed"
+}
+run_test 27K "basic ops on dir with foreign LMV"
+
# createtest also checks that device nodes are created and
# then visible correctly (#2091)
test_28() { # bug 2091
" fnv_1a_64 FNV-1a hash algorithm (default)\n" \
" all_char sum of characters % MDT_COUNT (not recommended)\n" \
"\tdefault_stripe: set default dirstripe of the directory\n" \
- "\tmode: the file access permission of the directory (octal)\n"
+ "\tmode: the file access permission of the directory (octal)\n" \
+ "To create dir with a foreign (free format) layout :\n" \
+ "setdirstripe|mkdir --foreign[=<foreign_type>] -x|-xattr <string> " \
+ "[--mode|-m mode] [--flags <hex>] <dir>\n" \
+ "\tmode: the mode of the directory\n" \
+ "\tforeign_type: none or daos\n"
/**
* command_t mirror_cmdlist - lfs mirror commands.
"usage: getdirstripe [--mdt-count|-c] [--mdt-index|-m|-i]\n"
" [--mdt-hash|-H] [--obd|-O <uuid>]\n"
" [--recursive|-r] [--yaml|-y]\n"
- " [--default|-D] <dir> ..."},
+ " [--verbose|-v] [--default|-D] <dir> ..."},
{"mkdir", lfs_setdirstripe, 0,
"To create a striped directory on a specified MDT. This can only\n"
"be done on MDT0 with the right of administrator.\n"
" [[!] --gid|-g|--group|-G <gid>|<gname>]\n"
" [[!] --uid|-u|--user|-U <uid>|<uname>] [[!] --pool <pool>]\n"
" [[!] --projid <projid>]\n"
+ " [[!] --foreign[=<foreign_type>]]\n"
" [[!] --layout|-L released,raid0,mdt]\n"
" [[!] --foreign[=<foreign_type>]]\n"
" [[!] --component-count [+-]<comp_cnt>]\n"
return 0;
}
-static uint32_t lov_check_foreign_type_name(const char *foreign_type_name)
+static uint32_t check_foreign_type_name(const char *foreign_type_name)
{
uint32_t i;
- for (i = 0; i < LOV_FOREIGN_TYPE_UNKNOWN; i++) {
- if (lov_foreign_type[i].lft_name == NULL)
+ for (i = 0; i < LU_FOREIGN_TYPE_UNKNOWN; i++) {
+ if (lu_foreign_types[i].lft_name == NULL)
break;
if (strcmp(foreign_type_name,
- lov_foreign_type[i].lft_name) == 0)
- return lov_foreign_type[i].lft_type;
+ lu_foreign_types[i].lft_name) == 0)
+ return lu_foreign_types[i].lft_type;
}
- return LOV_FOREIGN_TYPE_UNKNOWN;
+ return LU_FOREIGN_TYPE_UNKNOWN;
}
static const char *error_loc = "syserror";
char *template = NULL;
bool foreign_mode = false;
char *xattr = NULL;
- uint32_t type = LOV_FOREIGN_TYPE_NONE, flags = 0;
+ uint32_t type = LU_FOREIGN_TYPE_NONE, flags = 0;
char *mode_opt = NULL;
mode_t previous_umask = 0;
mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
type = strtoul(optarg, &end, 0);
if (*end) {
/* check name */
- type = lov_check_foreign_type_name(optarg);
- if (type == LOV_FOREIGN_TYPE_UNKNOWN) {
+ type = check_foreign_type_name(optarg);
+ if (type == LU_FOREIGN_TYPE_UNKNOWN) {
fprintf(stderr,
"%s %s: unrecognized foreign type '%s'\n",
progname, argv[0],
mode = strtoul(mode_opt, &end, 8);
if (*end != '\0') {
fprintf(stderr,
- "%s %s: bad MODE '%s'\n",
+ "%s %s: bad mode '%s'\n",
progname, argv[0], mode_opt);
return CMD_HELP;
}
}
}
- if (mode_opt != NULL && previous_umask != 0)
+ if (mode_opt != NULL)
umask(previous_umask);
free(param);
{ .val = 'E', .name = "component-end",
.has_arg = required_argument },
/* find { .val = 'F', .name = "fid", .has_arg = no_argument }, */
+ { .val = LFS_LAYOUT_FOREIGN_OPT,
+ .name = "foreign", .has_arg = optional_argument},
{ .val = 'g', .name = "gid", .has_arg = required_argument },
{ .val = 'G', .name = "group", .has_arg = required_argument },
{ .val = 'H', .name = "mdt-hash", .has_arg = required_argument },
param.fp_mirror_state = state;
}
break;
- case LFS_LAYOUT_FOREIGN_OPT: {
- /* all types by default */
- uint32_t type = LOV_FOREIGN_TYPE_UNKNOWN;
-
- if (optarg != NULL) {
- /* check pure numeric */
- type = strtoul(optarg, &endptr, 0);
- if (*endptr) {
- /* check name */
- type = lov_check_foreign_type_name(optarg);
- if (type == LOV_FOREIGN_TYPE_UNKNOWN) {
- fprintf(stderr,
- "%s %s: unrecognized foreign type '%s'\n",
- progname, argv[0],
- optarg);
- return CMD_HELP;
- }
- }
- }
- param.fp_foreign_type = type;
- param.fp_check_foreign = 1;
- param.fp_exclude_foreign = !!neg_opt;
- break;
- }
case 'c':
if (optarg[0] == '+') {
param.fp_stripe_count_sign = -1;
param.fp_check_comp_end = 1;
param.fp_exclude_comp_end = !!neg_opt;
break;
+ case LFS_LAYOUT_FOREIGN_OPT: {
+ /* all types by default */
+ uint32_t type = LU_FOREIGN_TYPE_UNKNOWN;
+
+ if (optarg != NULL) {
+ /* check pure numeric */
+ type = strtoul(optarg, &endptr, 0);
+ if (*endptr) {
+ /* check name */
+ type = check_foreign_type_name(optarg);
+ if (type == LU_FOREIGN_TYPE_UNKNOWN) {
+ fprintf(stderr,
+ "%s %s: unknown foreign type '%s'\n",
+ progname, argv[0],
+ optarg);
+ return CMD_HELP;
+ }
+ }
+ }
+ param.fp_foreign_type = type;
+ param.fp_check_foreign = 1;
+ param.fp_exclude_foreign = !!neg_opt;
+ break;
+ }
case 'g':
case 'G':
rc = name2gid(¶m.fp_gid, optarg);
{ .val = 'O', .name = "obd", .has_arg = required_argument },
{ .val = 'r', .name = "recursive", .has_arg = no_argument },
{ .val = 'T', .name = "mdt-count", .has_arg = no_argument },
+ { .val = 'v', .name = "verbose", .has_arg = no_argument },
{ .val = 'y', .name = "yaml", .has_arg = no_argument },
{ .name = NULL } };
int c, rc;
param.fp_get_lmv = 1;
while ((c = getopt_long(argc, argv,
- "cDHimO:rtTy", long_opts, NULL)) != -1)
+ "cDHimO:rtTvy", long_opts, NULL)) != -1)
{
switch (c) {
case 'c':
case 'r':
param.fp_recursive = 1;
break;
+ case 'v':
+ param.fp_verbose |= VERBOSE_DETAIL;
+ break;
case 'y':
param.fp_yaml = 1;
break;
default:
+ fprintf(stderr, "%s %s: unrecognized option '%s'\n",
+ progname, argv[0], argv[optind - 1]);
return CMD_HELP;
}
}
struct ll_statfs_buf *lsb = NULL;
char mntdir[PATH_MAX] = "";
bool auto_distributed = false;
+ bool foreign_mode = false;
+ char *xattr = NULL;
+ __u32 type = LU_FOREIGN_TYPE_DAOS, flags = 0;
struct option long_opts[] = {
{ .val = 'c', .name = "count", .has_arg = required_argument },
{ .val = 'd', .name = "delete", .has_arg = no_argument },
{ .val = 'D', .name = "default", .has_arg = no_argument },
{ .val = 'D', .name = "default_stripe", .has_arg = no_argument },
+ { .val = LFS_LAYOUT_FLAGS_OPT,
+ .name = "flags", .has_arg = required_argument },
+ { .val = LFS_LAYOUT_FOREIGN_OPT,
+ .name = "foreign", .has_arg = optional_argument},
{ .val = 'H', .name = "mdt-hash", .has_arg = required_argument },
#if LUSTRE_VERSION_CODE < OBD_OCD_VERSION(2, 17, 53, 0)
{ .val = 'i', .name = "mdt-index", .has_arg = required_argument },
#endif
{ .val = 'T', .name = "mdt-count", .has_arg = required_argument },
/* setstripe { .val = 'y', .name = "yaml", .has_arg = no_argument }, */
+ { .val = 'x', .name = "xattr", .has_arg = required_argument },
{ .name = NULL } };
setstripe_args_init(&lsa);
- while ((c = getopt_long(argc, argv, "c:dDi:H:m:o:t:T:", long_opts,
- NULL)) >= 0) {
+ while ((c = getopt_long(argc, argv, "c:dDi:H:m:o:t:T:x:",
+ long_opts, NULL)) >= 0) {
switch (c) {
case 0:
/* Long options. */
case 'D':
default_stripe = true;
break;
+ case LFS_LAYOUT_FOREIGN_OPT:
+ if (optarg != NULL) {
+ /* check pure numeric */
+ type = strtoul(optarg, &end, 0);
+ if (*end) {
+ /* check name */
+ type = check_foreign_type_name(optarg);
+ if (type == LU_FOREIGN_TYPE_UNKNOWN) {
+ fprintf(stderr,
+ "%s %s: unknown foreign type '%s'\n",
+ progname, argv[0],
+ optarg);
+ return CMD_HELP;
+ }
+ }
+ }
+ foreign_mode = true;
+ break;
+ case LFS_LAYOUT_FLAGS_OPT:
+ flags = strtoul(optarg, &end, 16);
+ if (*end != '\0') {
+ fprintf(stderr,
+ "%s %s: bad flags '%s'\n",
+ progname, argv[0], optarg);
+ return CMD_HELP;
+ }
+ break;
#if LUSTRE_VERSION_CODE < OBD_OCD_VERSION(3, 0, 53, 0)
case 't':
fprintf(stderr, "warning: '--hash-type' and '-t' "
case 'o':
mode_opt = optarg;
break;
+ case 'x':
+ xattr = optarg;
+ break;
default:
fprintf(stderr, "%s %s: unrecognized option '%s'\n",
progname, argv[0], argv[optind - 1]);
return CMD_HELP;
}
+ if (xattr && !foreign_mode) {
+ /* only print a warning as this is armless and will be
+ * ignored
+ */
+ fprintf(stderr,
+ "%s %s: xattr has been specified for non-foreign layout\n",
+ progname, argv[0]);
+ } else if (foreign_mode && !xattr) {
+ fprintf(stderr,
+ "%s %s: xattr must be provided in foreign mode\n",
+ progname, argv[0]);
+ return CMD_HELP;
+ }
+
+ if (foreign_mode && (delete || default_stripe || lsa.lsa_nr_tgts ||
+ lsa.lsa_tgts || setstripe_args_specified(&lsa))) {
+ fprintf(stderr,
+ "%s %s: only --xattr/--flags/--mode options are valid with --foreign\n",
+ progname, argv[0]);
+ return CMD_HELP;
+ }
+
if (!delete && lsa.lsa_stripe_off == LLAPI_LAYOUT_DEFAULT &&
- lsa.lsa_stripe_count == LLAPI_LAYOUT_DEFAULT) {
+ lsa.lsa_stripe_count == LLAPI_LAYOUT_DEFAULT && !foreign_mode) {
fprintf(stderr,
"%s %s: stripe offset and count must be specified\n",
progname, argv[0]);
previous_mode = umask(0);
}
+ /* foreign LMV/dir case */
+ if (foreign_mode) {
+ if (argc > optind + 1) {
+ fprintf(stderr,
+ "%s %s: cannot specify multiple foreign dirs\n",
+ progname, argv[0]);
+ return CMD_HELP;
+ }
+
+ dname = argv[optind];
+ result = llapi_dir_create_foreign(dname, mode, type, flags,
+ xattr);
+ if (result != 0)
+ fprintf(stderr,
+ "%s mkdir: can't create foreign dir '%s': %s\n",
+ progname, dname, strerror(-result));
+ return result;
+ }
+
/*
* initialize stripe parameters, in case param is converted to specific,
* i.e, 'lfs mkdir -i -1 -c N', always allocate space for lsp_tgts.
LMV_HASH_NAME_ALL_CHARS,
LMV_HASH_NAME_FNV_1A_64 };
-struct lustre_foreign_type lov_foreign_type[] = {
- {.lft_type = LOV_FOREIGN_TYPE_NONE, .lft_name = "none"},
- {.lft_type = LOV_FOREIGN_TYPE_DAOS, .lft_name = "daos"},
+struct lustre_foreign_type lu_foreign_types[] = {
+ {.lft_type = LU_FOREIGN_TYPE_NONE, .lft_name = "none"},
+ {.lft_type = LU_FOREIGN_TYPE_DAOS, .lft_name = "daos"},
/* must be the last element */
- {.lft_type = LOV_FOREIGN_TYPE_UNKNOWN, .lft_name = NULL}
+ {.lft_type = LU_FOREIGN_TYPE_UNKNOWN, .lft_name = NULL}
/* array max dimension must be <= UINT32_MAX */
};
return rc;
}
+/**
+ * Create a foreign directory.
+ *
+ * \param name the name of the directory to be created
+ * \param mode permission of the file if it is created, see mode in open(2)
+ * \param type foreign type to be set in LMV EA
+ * \param flags foreign flags to be set in LMV EA
+ * \param value foreign pattern to be set in LMV EA
+ *
+ * \retval 0 on success
+ * \retval negative errno on failure
+ */
+int llapi_dir_create_foreign(const char *name, mode_t mode, __u32 type,
+ __u32 flags, const char *value)
+{
+ struct lmv_foreign_md *lfm = NULL;
+ size_t lfm_size, len;
+ struct obd_ioctl_data data = { 0 };
+ char rawbuf[8192];
+ char *buf = rawbuf;
+ char *dirpath = NULL;
+ char *namepath = NULL;
+ char *dir;
+ char *filename;
+ int fd, rc;
+
+ len = strlen(value);
+ if (len > XATTR_SIZE_MAX - offsetof(struct lmv_foreign_md, lfm_value) ||
+ len <= 0) {
+ rc = -EINVAL;
+ llapi_error(LLAPI_MSG_ERROR, rc, "invalid LOV EA length %zu "
+ "(must be 0 < len < %zu)\n", len,
+ XATTR_SIZE_MAX -
+ offsetof(struct lmv_foreign_md, lfm_value));
+ return rc;
+ }
+ lfm_size = len + offsetof(struct lmv_foreign_md, lfm_value);
+ lfm = calloc(1, lfm_size);
+ if (lfm == NULL)
+ return -ENOMEM;
+
+ dirpath = strdup(name);
+ if (!dirpath) {
+ free(lfm);
+ return -ENOMEM;
+ }
+
+ namepath = strdup(name);
+ if (!namepath) {
+ free(dirpath);
+ free(lfm);
+ return -ENOMEM;
+ }
+
+ lfm->lfm_magic = LMV_MAGIC_FOREIGN;
+ lfm->lfm_length = len;
+ lfm->lfm_type = type;
+ lfm->lfm_flags = flags;
+ strncpy(lfm->lfm_value, value, len);
+
+ filename = basename(namepath);
+ dir = dirname(dirpath);
+
+ data.ioc_inlbuf1 = (char *)filename;
+ data.ioc_inllen1 = strlen(filename) + 1;
+ data.ioc_inlbuf2 = (char *)lfm;
+ data.ioc_inllen2 = lfm_size;
+ data.ioc_type = mode;
+ rc = llapi_ioctl_pack(&data, &buf, sizeof(rawbuf));
+ if (rc) {
+ llapi_error(LLAPI_MSG_ERROR, rc,
+ "error: LL_IOC_LMV_SETSTRIPE pack failed '%s'.",
+ name);
+ goto out;
+ }
+
+ fd = open(dir, O_DIRECTORY | O_RDONLY);
+ if (fd < 0) {
+ rc = -errno;
+ llapi_error(LLAPI_MSG_ERROR, rc, "unable to open '%s'", name);
+ goto out;
+ }
+
+ if (ioctl(fd, LL_IOC_LMV_SETSTRIPE, buf)) {
+ char *errmsg = "stripe already set";
+
+ rc = -errno;
+ if (errno != EEXIST && errno != EALREADY)
+ errmsg = strerror(errno);
+
+ llapi_err_noerrno(LLAPI_MSG_ERROR,
+ "dirstripe error on '%s': %s", name, errmsg);
+ }
+ close(fd);
+out:
+ free(namepath);
+ free(dirpath);
+ free(lfm);
+ return rc;
+}
int llapi_dir_create_pool(const char *name, int mode, int stripe_offset,
int stripe_count, int stripe_pattern,
int stripe_count;
int lmv_size;
- stripe_count = (__u32)param->fp_lmv_md->lum_stripe_count;
+ /* if foreign LMV case, fake stripes number */
+ if (param->fp_lmv_md->lum_magic == LMV_MAGIC_FOREIGN) {
+ struct lmv_foreign_md *lfm;
+
+ lfm = (struct lmv_foreign_md *)param->fp_lmv_md;
+ if (lfm->lfm_length < XATTR_SIZE_MAX -
+ offsetof(typeof(*lfm), lfm_value)) {
+ uint32_t size = lfm->lfm_length +
+ offsetof(typeof(*lfm), lfm_value);
+
+ stripe_count = lmv_foreign_to_md_stripes(size);
+ } else {
+ llapi_error(LLAPI_MSG_ERROR, -EINVAL,
+ "error: invalid %d foreign size "
+ "returned from ioctl",
+ lfm->lfm_length);
+ return -EINVAL;
+ }
+ } else {
+ stripe_count = param->fp_lmv_md->lum_stripe_count;
+ }
if (stripe_count <= param->fp_lmv_stripe_count)
return ret;
}
}
-static uint32_t lov_check_foreign_type(uint32_t foreign_type)
+static uint32_t check_foreign_type(uint32_t foreign_type)
{
uint32_t i;
- for (i = 0; i < LOV_FOREIGN_TYPE_UNKNOWN; i++) {
- if (lov_foreign_type[i].lft_name == NULL)
+ for (i = 0; i < LU_FOREIGN_TYPE_UNKNOWN; i++) {
+ if (lu_foreign_types[i].lft_name == NULL)
break;
- if (foreign_type == lov_foreign_type[i].lft_type)
+ if (foreign_type == lu_foreign_types[i].lft_type)
return i;
}
- return LOV_FOREIGN_TYPE_UNKNOWN;
+ return LU_FOREIGN_TYPE_UNKNOWN;
}
static void lov_dump_foreign_lmm(struct find_param *param, char *path,
llapi_printf(LLAPI_MSG_NORMAL, "%s\n", path);
if (param->fp_verbose & VERBOSE_DETAIL) {
- uint32_t type = lov_check_foreign_type(lfm->lfm_type);
+ uint32_t type = check_foreign_type(lfm->lfm_type);
llapi_printf(LLAPI_MSG_NORMAL, "lfm_magic: 0x%08X\n",
lfm->lfm_magic);
lfm->lfm_length);
llapi_printf(LLAPI_MSG_NORMAL, "lfm_type: 0x%08X",
lfm->lfm_type);
- if (type < LOV_FOREIGN_TYPE_UNKNOWN)
+ if (type < LU_FOREIGN_TYPE_UNKNOWN)
llapi_printf(LLAPI_MSG_NORMAL, " (%s)\n",
- lov_foreign_type[type].lft_name);
+ lu_foreign_types[type].lft_name);
else
llapi_printf(LLAPI_MSG_NORMAL, " (unknown)\n");
llapi_printf(LLAPI_MSG_NORMAL, "lfm_flags: 0x%08X\n",
lfm->lfm_flags);
}
+ llapi_printf(LLAPI_MSG_NORMAL, "lfm_value: '%.*s'\n",
+ lfm->lfm_length, lfm->lfm_value);
+ llapi_printf(LLAPI_MSG_NORMAL, "\n");
+}
+
+static void lmv_dump_foreign_lmm(struct find_param *param, char *path,
+ enum lov_dump_flags flags)
+{
+ struct lmv_foreign_md *lfm = (struct lmv_foreign_md *)param->fp_lmv_md;
+ bool yaml = flags & LDF_YAML;
+
+ if (!yaml && param->fp_depth && path)
+ llapi_printf(LLAPI_MSG_NORMAL, "%s\n", path);
+ if (param->fp_verbose & VERBOSE_DETAIL) {
+ uint32_t type = check_foreign_type(lfm->lfm_type);
+
+ llapi_printf(LLAPI_MSG_NORMAL, "lfm_magic: 0x%08X\n",
+ lfm->lfm_magic);
+ llapi_printf(LLAPI_MSG_NORMAL, "lfm_length: %u\n",
+ lfm->lfm_length);
+ llapi_printf(LLAPI_MSG_NORMAL, "lfm_type: 0x%08X",
+ lfm->lfm_type);
+ if (type < LU_FOREIGN_TYPE_UNKNOWN)
+ llapi_printf(LLAPI_MSG_NORMAL, " (%s)\n",
+ lu_foreign_types[type].lft_name);
+ else
+ llapi_printf(LLAPI_MSG_NORMAL, " (unknown)\n");
+
+ llapi_printf(LLAPI_MSG_NORMAL, "lfm_flags: 0x%08X\n",
+ lfm->lfm_flags);
+ }
llapi_printf(LLAPI_MSG_NORMAL, "lfm_value: '%.*s'\n",
lfm->lfm_length, lfm->lfm_value);
llapi_printf(LLAPI_MSG_NORMAL, "\n");
case LOV_USER_MAGIC_COMP_V1:
lov_dump_comp_v1(param, path, flags);
break;
+ case LMV_MAGIC_FOREIGN:
+ lmv_dump_foreign_lmm(param, path, flags);
+ break;
default:
llapi_printf(LLAPI_MSG_NORMAL, "unknown lmm_magic: %#x "
"(expecting one of %#x %#x %#x %#x)\n",
lfm = (void *)¶m->fp_lmd->lmd_lmm;
if (lfm->lfm_magic != LOV_USER_MAGIC_FOREIGN) {
- if (param->fp_foreign_type == LOV_FOREIGN_TYPE_UNKNOWN)
+ if (param->fp_foreign_type == LU_FOREIGN_TYPE_UNKNOWN)
+ return param->fp_exclude_foreign ? 1 : -1;
+ return -1;
+ } else {
+ if (param->fp_foreign_type == LU_FOREIGN_TYPE_UNKNOWN ||
+ lfm->lfm_type == param->fp_foreign_type)
+ return param->fp_exclude_foreign ? -1 : 1;
+ return param->fp_exclude_foreign ? 1 : -1;
+ }
+ }
+
+ if (S_ISDIR(param->fp_lmd->lmd_st.st_mode)) {
+ struct lmv_foreign_md *lfm;
+
+ lfm = (void *)param->fp_lmv_md;
+ if (lfm->lfm_magic != LMV_MAGIC_FOREIGN) {
+ if (param->fp_foreign_type == LU_FOREIGN_TYPE_UNKNOWN)
return param->fp_exclude_foreign ? 1 : -1;
return -1;
} else {
- if (param->fp_foreign_type == LOV_FOREIGN_TYPE_UNKNOWN ||
+ if (param->fp_foreign_type == LU_FOREIGN_TYPE_UNKNOWN ||
lfm->lfm_type == param->fp_foreign_type)
return param->fp_exclude_foreign ? -1 : 1;
return param->fp_exclude_foreign ? 1 : -1;
decision = 0;
if (decision == 0) {
- if (param->fp_check_mdt_count || param->fp_check_hash_type) {
+ if (dir && (param->fp_check_mdt_count ||
+ param->fp_check_hash_type || param->fp_check_foreign)) {
param->fp_get_lmv = 1;
ret = cb_get_dirstripe(path, dir, param);
- if (ret != 0)
+ if (ret != 0) {
+ /* XXX this works to decide for foreign
+ * criterion only
+ */
+ if (errno == ENODATA &&
+ param->fp_check_foreign) {
+ if (param->fp_exclude_foreign)
+ goto foreign;
+ goto decided;
+ }
return ret;
+ }
}
param->fp_lmd->lmd_lmm.lmm_magic = 0;
}
if (param->fp_check_mdt_count) {
+ if (param->fp_lmv_md->lum_magic == LMV_MAGIC_FOREIGN) {
+ decision = -1;
+ goto decided;
+ }
+
decision = find_value_cmp(
param->fp_lmv_md->lum_stripe_count,
param->fp_mdt_count,
if (param->fp_check_hash_type) {
__u32 found;
+ if (param->fp_lmv_md->lum_magic == LMV_MAGIC_FOREIGN) {
+ decision = -1;
+ goto decided;
+ }
+
found = param->fp_lmv_md->lum_hash_type & param->fp_hash_type;
if ((found && param->fp_exclude_hash_type) ||
(!found && !param->fp_exclude_hash_type)) {
goto decided;
}
+foreign:
llapi_printf(LLAPI_MSG_NORMAL, "%s", path);
if (param->fp_zero_end)
llapi_printf(LLAPI_MSG_NORMAL, "%c", '\0');
liblustreapi_initialized;
l_ioctl;
mdt_hash_name;
- lov_foreign_type;
+ lu_foreign_types;
Parser_*;
register_ioc_*;
local: