X(LS3_OBJECT_ATTR_BASE, "ctime"),
X(LS3_OBJECT_ATTR_SELF_FID, "self_fid"),
X(LS3_OBJECT_ATTR_FILE_FID, "file_fid"),
+ X(LS3_OBJECT_ATTR_SELF_FID, "lma"),
+ X(LS3_OBJECT_ATTR_FILTER_FID, "filter_fid"),
X(LS3_OBJECT_ATTR_LINKS, "links"),
X(LS3_OBJECT_ATTR_HSM, "hsm"),
X(LS3_OBJECT_ATTR_LOV, "lov"),
{
struct ls3_object_attrs *loa = ls3_attrs(LS3_OBJECT_ATTR_SELF_FID);
- return ls3_scm_from_fid(&loa->loa_self_fid);
+ return ls3_scm_from_fid(loa_self_fid(loa));
}
SCM_DEFINE(ls3_scm_links_list, "links", 0, 0, 0,
(), "print self FID of current file or OST object")
{
struct ls3_object_attrs *loa = ls3_attrs(LS3_OBJECT_ATTR_SELF_FID);
- const struct lu_fid *fid = &loa->loa_self_fid;
+ const struct lu_fid *fid = loa_self_fid(loa);
LS3_PRINT_DELIM(DFID, PFID(fid));
unsigned long c_bits;
struct json_object *obj;
const char *str;
+ int json_c_to_string_flags = JSON_C_TO_STRING_PLAIN;
+
+#ifdef JSON_C_TO_STRING_NOSLASHESCAPE
+ /* This means "Don't slash escape forward slashes." But it's
+ * not available until json-c-0.13 */
+ json_c_to_string_flags |= JSON_C_TO_STRING_NOSLASHESCAPE;
+#endif
if (SCM_UNBNDP(bits))
c_bits = print_json_attrs;
SCM_VALIDATE_ULONG_COPY(1, bits, c_bits);
obj = ls3_object_attrs_to_json(lc->lc_instance, lc->lc_object, lc->lc_attrs, c_bits);
- str = json_object_to_json_string_ext(obj, JSON_C_TO_STRING_PLAIN);
+ str = json_object_to_json_string_ext(obj, json_c_to_string_flags);
LS3_PRINT_DELIM("%s", str);
return arr;
}
+static struct json_object *lipe_filter_fid_to_json(const struct filter_fid *ff, size_t size)
+{
+ struct json_object *obj = json_object_new_object();
+ struct json_object *layout;
+
+ json_object_object_add(obj, "parent", fid_to_json(&ff->ff_parent));
+
+ if (size < sizeof(*ff))
+ return obj;
+
+ layout = json_object_new_object();
+
+ json_object_object_add(layout, "stripe_size", json_object_new_int64(ff->ff_layout.ol_stripe_size));
+ json_object_object_add(layout, "stripe_count", json_object_new_int64(ff->ff_layout.ol_stripe_count));
+ json_object_object_add(layout, "comp_start", json_object_new_int64(ff->ff_layout.ol_comp_start));
+ json_object_object_add(layout, "comp_end", json_object_new_int64(ff->ff_layout.ol_comp_end));
+ json_object_object_add(layout, "comp_id", json_object_new_int64(ff->ff_layout.ol_comp_id));
+
+ json_object_object_add(obj, "layout", layout);
+ json_object_object_add(obj, "layout_version", json_object_new_int64(ff->ff_layout_version));
+ json_object_object_add(obj, "range", json_object_new_int64(ff->ff_range));
+
+ return obj;
+}
+
+static struct json_object *lipe_lma_to_json(const struct lustre_mdt_attrs *lma)
+{
+ struct json_object *obj = json_object_new_object();
+ struct json_object *compat = json_object_new_array();
+ struct json_object *incompat = json_object_new_array();
+
+#define X(f, n) \
+ if (lma->lma_compat & (f)) \
+ json_object_array_add(compat, json_object_new_string(n))
+ X(LMAC_NOT_IN_OI, "not_in_oi");
+ X(LMAC_FID_ON_OST, "fid_on_ost");
+ X(LMAC_STRIPE_INFO, "stripe_info");
+ X(LMAC_COMP_INFO, "comp_info");
+ X(LMAC_IDX_BACKUP, "idx_backup");
+#undef X
+
+#define X(f, n) \
+ if (lma->lma_compat & (f)) \
+ json_object_array_add(incompat, json_object_new_string(n))
+ X(LMAI_AGENT, "agent");
+ X(LMAI_REMOTE_PARENT, "remote_parent");
+ X(LMAI_STRIPED, "striped_directory");
+ X(LMAI_ORPHAN, "orphan");
+ X(LMAI_ENCRYPT, "encrypt");
+#undef X
+
+ json_object_object_add(obj, "self_fid", fid_to_json(&lma->lma_self_fid));
+ json_object_object_add(obj, "compat", compat);
+ json_object_object_add(obj, "_compat", json_object_new_int64(lma->lma_compat));
+ json_object_object_add(obj, "incompat", incompat);
+ json_object_object_add(obj, "_incompat", json_object_new_int64(lma->lma_incompat));
+
+ return obj;
+}
+
+static struct json_object *lipe_hsm_to_json(const struct hsm_user_state *hus)
+{
+ struct json_object *obj = json_object_new_object();
+ struct json_object *states = json_object_new_array();
+
+#define X(f, n) \
+ if (hus->hus_states & (f)) \
+ json_object_array_add(states, json_object_new_string(n))
+ X(HS_EXISTS, "exists");
+ X(HS_DIRTY, "dirty");
+ X(HS_RELEASED, "released");
+ X(HS_ARCHIVED, "archived");
+ X(HS_NORELEASE, "norelease");
+ X(HS_NOARCHIVE, "noarchive");
+ X(HS_LOST, "lost"); /* Such a great show. */
+ X(HS_PCCRW, "pccrw");
+ X(HS_PCCRO, "pccro");
+#undef X
+
+ json_object_object_add(obj, "states", states);
+ json_object_object_add(obj, "_states", json_object_new_int64(hus->hus_states));
+ json_object_object_add(obj, "archive_id", json_object_new_int64(hus->hus_archive_id));
+
+ return obj;
+}
+
static struct json_object *lipe_som_attrs_to_json(const struct lustre_som_attrs *lsa)
{
struct json_object *obj;
LS3_JSON_ENCODE_I(projid);
LS3_JSON_ENCODE_I(flags);
-/* TODO HSM, LOV, LMV FILTER_FID */
+/* TODO LOV, LMV */
LS3_JSON_ENCODE_J(file_fid, fid_to_json(&loa->loa_file_fid));
-LS3_JSON_ENCODE_J(self_fid, fid_to_json(&loa->loa_self_fid));
+LS3_JSON_ENCODE_J(self_fid, fid_to_json(loa_self_fid(loa)));
+LS3_JSON_ENCODE_J(filter_fid, lipe_filter_fid_to_json(&loa->loa_filter_fid, loa->loa_filter_fid_size));
+LS3_JSON_ENCODE_J(lma, lipe_lma_to_json(&loa->loa_lma));
+LS3_JSON_ENCODE_J(hsm, lipe_hsm_to_json(&loa->loa_hsm_state));
LS3_JSON_ENCODE_J(links, lipe_link_entry_list_to_json(&loa->loa_links));
LS3_JSON_ENCODE_J(paths, lipe_path_entry_list_to_json(&loa->loa_paths));
LS3_JSON_ENCODE_J(som, lipe_som_attrs_to_json(&loa->loa_som));
[LS3_JSON_BIT_SIZE] = { "size", &ls3_json_encode_size, LS3_OBJECT_ATTR_SIZE },
[LS3_JSON_BIT_BLOCKS] = { "blocks", &ls3_json_encode_blocks, LS3_OBJECT_ATTR_SIZE },
[LS3_JSON_BIT_FILE_FID] = { "file_fid", &ls3_json_encode_file_fid, LS3_OBJECT_ATTR_FILE_FID },
- [LS3_JSON_BIT_SELF_FID] = { "self_fid",&ls3_json_encode_self_fid, LS3_OBJECT_ATTR_SELF_FID },
+ [LS3_JSON_BIT_SELF_FID] = { "self_fid", &ls3_json_encode_self_fid, LS3_OBJECT_ATTR_SELF_FID },
+ [LS3_JSON_BIT_FILTER_FID] = { "filter_fid", &ls3_json_encode_filter_fid, LS3_OBJECT_ATTR_FILTER_FID },
+ [LS3_JSON_BIT_LMA] = { "lma", &ls3_json_encode_lma, LS3_OBJECT_ATTR_SELF_FID },
+ [LS3_JSON_BIT_HSM] = { "hsm", &ls3_json_encode_hsm, LS3_OBJECT_ATTR_HSM },
/* [LS3_JSON_BIT_LOV] = { "lov", &ls3_json_encode_lov, LS3_OBJECT_ATTR_LOV }, */
/* [LS3_JSON_BIT_LMV] = { "lmv", &ls3_json_encode_lmv, LS3_OBJECT_ATTR_LMV }, */
[LS3_JSON_BIT_LINKS] = { "links", &ls3_json_encode_links, LS3_OBJECT_ATTR_LINKS },
loa->loa_attr_bits = 0;
loa->loa_ino = 0;
memset(&loa->loa_file_fid, 0, sizeof(loa->loa_file_fid));
- memset(&loa->loa_self_fid, 0, sizeof(loa->loa_self_fid));
+ memset(&loa->loa_lma, 0, sizeof(loa->loa_lma));
lipe_object_attrs_links_fini(loa);
lipe_object_attrs_paths_fini(loa);
lipe_object_attrs_xattrs_fini(loa);
LS3_JSON_BIT_BLOCKS,
LS3_JSON_BIT_FILE_FID,
LS3_JSON_BIT_SELF_FID,
+ LS3_JSON_BIT_FILTER_FID,
+ LS3_JSON_BIT_LMA,
+ LS3_JSON_BIT_HSM,
LS3_JSON_BIT_LOV,
LS3_JSON_BIT_LMV,
LS3_JSON_BIT_POOLS,
LS3_JSON_ATTR_BLOCKS = 1U << LS3_JSON_BIT_BLOCKS,
LS3_JSON_ATTR_FILE_FID = 1U << LS3_JSON_BIT_FILE_FID,
LS3_JSON_ATTR_SELF_FID = 1U << LS3_JSON_BIT_SELF_FID,
+ LS3_JSON_ATTR_FILTER_FID = 1U << LS3_JSON_BIT_FILTER_FID,
+ LS3_JSON_ATTR_LMA = 1U << LS3_JSON_BIT_LMA,
+ LS3_JSON_ATTR_HSM = 1U << LS3_JSON_BIT_HSM,
LS3_JSON_ATTR_LOV = 1U << LS3_JSON_BIT_LOV,
LS3_JSON_ATTR_LMV = 1U << LS3_JSON_BIT_LMV,
LS3_JSON_ATTR_POOLS = 1U << LS3_JSON_BIT_POOLS,
gid_t loa_gid;
int64_t loa_projid;
struct lu_fid loa_file_fid;
- struct lu_fid loa_self_fid;
- uint32_t loa_lma_compat;
- uint32_t loa_lma_incompat;
+ struct lustre_mdt_attrs loa_lma;
void *loa_link_buf;
size_t loa_link_buf_size;
void *loa_lmv_buf;
struct lipe_list_head loa_xattrs;
};
+static inline const struct lu_fid *loa_self_fid(const struct ls3_object_attrs *loa)
+{
+ return &loa->loa_lma.lma_self_fid;
+}
+
void ls3_list_json_attrs(void);
int ls3_json_attrs_parse(const char *str, enum ls3_json_attr *attrs);
struct lipe_object *lo,
struct ls3_object_attrs *loa)
{
- struct lustre_mdt_attrs *lma;
+ const struct lustre_mdt_attrs *lma;
char buf[XATTR_SIZE_MAX];
int size;
int rc;
if (rc < 0)
return rc;
- lma = (struct lustre_mdt_attrs *)buf;
- fid_le_to_cpu(&loa->loa_self_fid, &lma->lma_self_fid);
- loa->loa_lma_compat = ext2fs_le32_to_cpu(lma->lma_compat);
- loa->loa_lma_incompat = ext2fs_le32_to_cpu(lma->lma_incompat);
+ lma = (const struct lustre_mdt_attrs *)buf;
+ fid_le_to_cpu(&loa->loa_lma.lma_self_fid, &lma->lma_self_fid);
+ loa->loa_lma.lma_compat = ext2fs_le32_to_cpu(lma->lma_compat);
+ loa->loa_lma.lma_incompat = ext2fs_le32_to_cpu(lma->lma_incompat);
loa->loa_attr_bits |= LS3_OBJECT_ATTR_SELF_FID;
if (rc < 0)
return rc;
- loa->loa_file_fid = loa->loa_self_fid;
+ loa->loa_file_fid = *loa_self_fid(loa);
} else if (li->li_device_is_ost) {
rc = ldiskfs_read_attr_filter_fid(li, lo, loa);
if (rc < 0)
if (rc < 0)
return rc;
- if (loa->loa_lma_incompat & LMAI_ORPHAN) {
+ if (loa->loa_lma.lma_incompat & LMAI_ORPHAN) {
/* Then no links and loa_links is empty so good. */
goto out_ok;
}
* crashes when we try to access objects by or using
* fid2path. */
if ((li->li_required_attrs & LS3_OBJECT_ATTR_SELF_FID) &&
- !fid_is_norm(&loa->loa_self_fid) && !fid_is_idif(&loa->loa_self_fid))
+ !fid_is_norm(loa_self_fid(loa)) && !fid_is_idif(loa_self_fid(loa)))
continue;
if (lo_is_dir_stripe(li, lo, loa))
function init_lipe_scan3_env() {
# Check "$MOUNT" is a Lustre client mount point.
local fid=$($LFS path2fid "$MOUNT")
+ local file
+ local index
+
[[ "$fid" == "$ROOT_FID" ]] || error "'$MOUNT' is not a lustre client mount"
find "$MOUNT" -mindepth 1 -delete || error "cannot clean '$MOUNT'"
find "$MOUNT" -mindepth 1 | grep . && error "find -delete did not delete all files from '$MOUNT'"
- sync
-}
-
-function init_lipe_scan3_env_file() {
- local file="$1"
- local index
-
- init_lipe_scan3_env
+ for file in "$@"; do
+ mcreate $file || error "cannot create $file"
+ index=$($LFS getstripe --mdt-index $file)
+ ((index == 0)) || error "file '$file' is not on MDT0000"
+ done
- mcreate $file || error "cannot create $file"
- index=$($LFS getstripe --mdt-index $file)
- ((index == 0)) || error "file '$file' is not on MDT0000"
+ sync
sync
}
local tmp=$(mktemp -d)
local fid
- init_lipe_scan3_env_file "$file"
+ init_lipe_scan3_env "$file"
fid=$($LFS path2fid "$file")
touch $tmp/$tfile
local file=$MOUNT/$tfile
local proc
- init_lipe_scan3_env_file "$file"
+ init_lipe_scan3_env "$file"
lipe_scan3 "$device" --print-self-fid
lipe_scan3_format "$device" '(self-fid)'
local file=$MOUNT/$tfile
local mode
- init_lipe_scan3_env_file "$file"
+ init_lipe_scan3_env "$file"
mode=0$(stat --format=%a $file) # octal access rights
expect_attr "$device" mode $((S_IFREG | mode)) # $((...)) converts to decimal
local file=$MOUNT/$tfile
local id
- init_lipe_scan3_env_file "$file"
+ init_lipe_scan3_env "$file"
id=$(stat --format=%u $file) # uid
expect_attr "$device" uid "$id"
local file=$MOUNT/$tfile
local time
- init_lipe_scan3_env_file "$file"
+ init_lipe_scan3_env "$file"
time=$(stat --format=%X $file) # atime
expect_attr "$device" atime "$time"
local file=$MOUNT/$tfile
local size
- init_lipe_scan3_env_file "$file"
+ init_lipe_scan3_env "$file"
expect_attr "$device" size 0
local device="$(facet_device $facet)"
local file=$MOUNT/$tfile
- init_lipe_scan3_env_file "$file"
+ init_lipe_scan3_env "$file"
expect_attr "$device" nlink 1
ln $file $file-2
local file=$MOUNT/$tfile
local id
- init_lipe_scan3_env_file "$file"
+ init_lipe_scan3_env "$file"
id=$($LFS project "$file" | awk '{ print $1 }')
expect_attr "$device" projid "$id"
local file=$MOUNT/$tfile
local fid
- init_lipe_scan3_env_file "$file"
+ init_lipe_scan3_env "$file"
fid=$($LFS path2fid $file)
expect_attr "$device" file-fid "$fid"
expect_attr "$device" self-fid "$fid"
local file=$MOUNT/$tfile
local fd
- init_lipe_scan3_env_file "$file"
+ init_lipe_scan3_env "$file"
# (links) returns a list of parent-fid, name pairs
# (([0x200000007:0x1:0x0] . "f0") ...)
local device="$(facet_device $facet)"
local file=$MOUNT/$tfile
- init_lipe_scan3_env_file "$file"
+ init_lipe_scan3_env "$file"
expect_expr "$device" '(absolute-paths)' "($file)"
expect_expr "$device" '(relative-paths)' "($tfile)"
}
run_test 110 "lipe_scan3 som attr works"
+test_111() {
+ local facet=mds1
+ local device="$(facet_device $facet)"
+ local file=$MOUNT/$tfile
+ local fid
+ local fid2
+
+ init_lipe_scan3_env "$file"
+ fid=$($LFS path2fid "$file")
+
+ # {
+ # "lma": {
+ # "self_fid": "[0x200000bd9:0x8c:0x0]",
+ # "compat": [],
+ # "_compat": 0,
+ # "incompat": [],
+ # "_incompat": 0
+ # }
+ # }
+
+ fid2=$(lipe_scan3 "$device" --print-json=lma | jq --raw-output .lma.self_fid)
+ [[ "$fid" == "$fid2" ]] || error "lma.self_fid expected '$fid', got '$fid2'"
+}
+run_test 111 "lipe_scan3 lma attr does the right thing"
+
+test_112() {
+ local facet=mds1
+ local device="$(facet_device $facet)"
+ local file=$MOUNT/$tfile
+ local hsm
+
+ init_lipe_scan3_env "$file"
+
+ # FIXME Make a better test.
+
+ hsm=$(lipe_scan3 "$device" --print-json=hsm)
+ [[ "$hsm" == "{}" ]] || error "hsm expected '{}', got '$hsm'"
+}
+run_test 112 "lipe_scan3 hsm attr does the right thing"
+
+test_113() {
+ local facet=mds1
+ local device="$(facet_device $facet)"
+ local file=$MOUNT/$tfile
+ local a2
+
+ init_lipe_scan3_env "$file"
+
+ # FIXME Make a better test. We scan the mds1 for
+ # filter_fid. This just checks that ls3 understands the
+ # filter_fid attr.
+
+ a2=$(lipe_scan3 "$device" --print-json=filter_fid)
+ [[ "$a2" == "{}" ]] || error "filter_fid expected '', got '$a2'"
+}
+run_test 113 "lipe_scan3 filter_fid does the right thing"
+
test_120() {
local facet=mds1
local device="$(facet_device $facet)"
local file=$MOUNT/$tfile
- local fd
- init_lipe_scan3_env_file "$file"
+ init_lipe_scan3_env "$file"
echo XXX > "$file"
expect_expr "$device" '(car (assoc "trusted.lov" (xattrs)))' trusted.lov
local file=$MOUNT/$tfile
local -a ost_indexes
- init_lipe_scan3_env
+ init_lipe_scan3_env "$file"
$LFS setstripe -c -1 "$file"
- echo XXX > "$file"
ost_indexes=($($LFS getstripe --yaml "$file" | yq '.lmm_objects[] | .l_ost_idx'))
expect_expr "$device" '(lov-pools)' '()'
local file=$MOUNT/$tfile
local proc
- init_lipe_scan3_env_file "$file"
+ init_lipe_scan3_env "$file"
lipe_scan3_format "$device" '(lipe-scan-device-name)'
expect_attr "$device" lipe-scan-fsname "$FSNAME"
local file=$MOUNT/$tfile
local rc
- init_lipe_scan3_env_file "$file"
+ init_lipe_scan3_env "$file"
lipe_scan3_body "$device" '(lipe-scan-break 7)'
rc=$?
local fid
local out
- init_lipe_scan3_env_file "$file"
+ init_lipe_scan3_env "$file"
fid=$($LFS path2fid "$file")
lipe_scan3 "$device" --print-file-fid
local file=$MOUNT/$tfile
local out
- init_lipe_scan3_env_file "$file"
+ init_lipe_scan3_env "$file"
out=$(lipe_scan3 "$device" --print-absolute-path)
[[ "$out" == "$file" ]] || error "--print-absolute-path should print absolute path"
local out
local expect
- init_lipe_scan3_env_file "$file"
+ init_lipe_scan3_env "$file"
ln "$file" "$file-1"
ln "$file" "$file-2"