return TOKEN_TEST;
}
--(amin|atime|cmin|ctime|gid|group|iname|inum|links|mmin|mtime|name|path|perm|pool|projid|size|type|uid|user)\0 {
+-(amin|atime|blocks|cmin|crtime|ctime|gid|group|iname|inum|links|mirror-count|mmin|mtime|name|path|perm|pool|projid|size|stripe-count|type|uid|user)\0 {
LF3_DEBUG("unary '%s'\n", yytext);
expr_arg_begin = lf3_arg_index;
expr_arg_end = lf3_arg_index + 2;
return x != 0 && (x & (x - 1)) == 0;
}
-static char *lf3_size_expr(int begin, int end)
+static char *lf3_size_expr(const char *which, int begin, int end)
{
const char *size_str = lf3_arg[begin + 1];
char cmp;
__ull unit;
int rc;
- /* -size n[cwbkMG]
- * File uses n units of space, rounding up. The following suffixes can be used: */
+ /* @which should be "size" or "blocks"
+ * -blocks n[cwbkMG]
+ * -size n[cwbkMG]
+ * File uses n units of space, rounding up. Optional +- prefix applies. */
assert(begin + 2 == end);
* matches files from 0 to 1,048,575 bytes. */
if ((cmp == '=' && val == 0) || unit == 1)
- return xsprintf("(%c (size) %llu)", cmp, val);
+ return xsprintf("(%c (%s) %llu)", cmp, which, val);
else if (is_power_of_2(unit))
- return xsprintf("(%c (round-up-power-of-2 (size) %llu) %llu)",
+ return xsprintf("(%c (round-up-power-of-2 (%s) %llu) %llu)",
cmp,
+ which,
unit,
unit * val);
else
- return xsprintf("(%c (round-up (size) %llu) %llu)",
+ return xsprintf("(%c (round-up (%s) %llu) %llu)",
cmp,
+ which,
unit,
unit * val);
}
{ NULL, 0 },
};
-static char *lf3_time_expr(char which, __ull unit_sec_def, int begin, int end)
+static char *lf3_time_expr(const char *which, __ull unit_sec_def, int begin, int end)
{
const char *time_str = lf3_arg[begin + 1];
char cmp;
__ull unit_sec;
int rc;
+ /* @which should be one of "atime", "mtime", "ctime", "crtime". */
assert(begin + 2 == end);
- assert(which == 'a' || which == 'm' || which == 'c');
rc = lf3_parse_numeric(lf3_time_units, time_str, &cmp, &val, &unit_sec);
if (rc < 0)
return xsprintf("(%c" /* cmp */
" (quotient (- %llu" /* now */
- " (%ctime))" /* which */
+ " (%s))" /* which */
" %llu)" /* unit_sec */
" %llu)" /* val */,
cmp, lf3_now, which, unit_sec, val);
X1(iname);
X1(path);
X1(ipath);
- X1(size);
X1(type);
X1(exec);
X1(perm);
X1(fprintf);
X1(delete);
+ X2("size", lf3_size_expr("size", begin, end));
+ X2("blocks", lf3_size_expr("blocks", begin, end));
+
/* lipe_scan attribute names are consistent with struct stat member names. */
X2("inum", lf3_numeric_expr("ino", begin, end)); // find uses "-inum", lipe_scan uses "ino".
X2("uid", lf3_numeric_expr("uid", begin, end)); // ...
X2("gid", lf3_numeric_expr("gid", begin, end));
X2("projid", lf3_numeric_expr("projid", begin, end));
X2("links", lf3_numeric_expr("nlink", begin, end));
-
- X2("amin", lf3_time_expr('a', 60, begin, end));
- X2("atime", lf3_time_expr('a', 86400, begin, end));
- X2("cmin", lf3_time_expr('c', 60, begin, end));
- X2("ctime", lf3_time_expr('c', 86400, begin, end));
- X2("mmin", lf3_time_expr('m', 60, begin, end));
- X2("mtime", lf3_time_expr('m', 86400, begin, end));
+ X2("mirror-count", lf3_numeric_expr("mirror-count", begin, end));
+ X2("stripe-count", lf3_numeric_expr("stripe-count", begin, end));
+
+ X2("amin", lf3_time_expr("atime", 60, begin, end));
+ X2("atime", lf3_time_expr("atime", 86400, begin, end));
+ X2("cmin", lf3_time_expr("ctime", 60, begin, end));
+ X2("ctime", lf3_time_expr("ctime", 86400, begin, end));
+ X2("mmin", lf3_time_expr("mtime", 60, begin, end));
+ X2("mtime", lf3_time_expr("mtime", 86400, begin, end));
+ X2("crtime", lf3_time_expr("crtime", 86400, begin, end));
X2("true", xstrdup("#t"));
X2("false", xstrdup("#f"));
X(LS3_OBJECT_ATTR_BASE, "atime"),
X(LS3_OBJECT_ATTR_BASE, "mtime"),
X(LS3_OBJECT_ATTR_BASE, "ctime"),
+ X(LS3_OBJECT_ATTR_BASE, "crtime"),
X(LS3_OBJECT_ATTR_SELF_FID, "self_fid"),
X(LS3_OBJECT_ATTR_FILE_FID, "file_fid"),
X(LS3_OBJECT_ATTR_SELF_FID, "lma"),
LS3_DEF_ATTR_U("atime", atime);
LS3_DEF_ATTR_U("blocks", blocks); /* 512B blocks */
LS3_DEF_ATTR_U("ctime", ctime);
+LS3_DEF_ATTR_U("crtime", crtime);
LS3_DEF_ATTR_U("flags", flags);
LS3_DEF_ATTR_U("gid", gid);
LS3_DEF_ATTR_U("ino", ino);
}
#undef FUNC_NAME
+SCM_DEFINE(ls3_scm_lov_mirror_count, "lov-mirror-count", 0, 0, 0,
+ (), "return mirror count of current file")
+{
+ struct ls3_object_attrs *loa = ls3_attrs_try(LS3_OBJECT_ATTR_LOV);
+ uint16_t count = 0;
+ int rc;
+
+ /* TODO Distinguish between missing xattr and other error. */
+ if (!(loa->loa_attr_bits & LS3_OBJECT_ATTR_LOV))
+ return scm_from_int(0);
+
+ /* XXX llapi_layout_*() functions return -1 on error and set errno. */
+ assert(loa->loa_layout != NULL);
+
+ rc = llapi_layout_mirror_count_get(loa->loa_layout, &count);
+ if (rc < 0)
+ ls3_throw_read_attr_error(LS3_OBJECT_ATTR_LOV,
+ errno != 0 ? errno : EINVAL);
+
+ return scm_from_uint(count);
+}
+
+SCM_DEFINE(ls3_scm_lov_stripe_count, "lov-stripe-count", 0, 0, 0,
+ (), "return stripe count of current file")
+{
+ struct ls3_object_attrs *loa = ls3_attrs_try(LS3_OBJECT_ATTR_LOV);
+ uint64_t count = 0;
+ int rc;
+
+ /* TODO Distinguish between missing xattr and other error. */
+ if (!(loa->loa_attr_bits & LS3_OBJECT_ATTR_LOV))
+ return scm_from_int(0);
+
+ /* XXX llapi_layout_*() functions return -1 on error and set errno. */
+ assert(loa->loa_layout != NULL);
+
+ rc = llapi_layout_get_last_init_comp(loa->loa_layout);
+ if (rc < 0)
+ goto out;
+
+ rc = llapi_layout_stripe_count_get(loa->loa_layout, &count);
+out:
+ if (rc < 0)
+ ls3_throw_read_attr_error(LS3_OBJECT_ATTR_LOV,
+ errno != 0 ? errno : EINVAL);
+
+ return scm_from_uint64(count);
+}
+
SCM_DEFINE(ls3_scm_lov_pools_list, "lov-pools", 0, 0, 0,
(), "return all pools from LOV of current file")
{
"atime",
"blocks",
"ctime",
+ "crtime",
"flags",
"gid",
"ino",
"relative-paths",
"xattrs",
"xattr-ref",
+ "lov-mirror-count",
+ "lov-stripe-count",
"lov-ost-indexes",
"lov-pools",
"print-json",
LS3_JSON_ENCODE_I(atime);
LS3_JSON_ENCODE_I(mtime);
LS3_JSON_ENCODE_I(ctime);
+LS3_JSON_ENCODE_I(crtime);
LS3_JSON_ENCODE_I(blocks);
LS3_JSON_ENCODE_I(projid);
LS3_JSON_ENCODE_I(flags);
[LS3_JSON_BIT_ATIME] = { "atime", &ls3_json_encode_atime, LS3_OBJECT_ATTR_BASE },
[LS3_JSON_BIT_MTIME] = { "mtime", &ls3_json_encode_mtime, LS3_OBJECT_ATTR_BASE },
[LS3_JSON_BIT_CTIME] = { "ctime", &ls3_json_encode_ctime, LS3_OBJECT_ATTR_BASE },
+ [LS3_JSON_BIT_CRTIME] = { "crtime", &ls3_json_encode_crtime, LS3_OBJECT_ATTR_BASE },
[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_ATIME,
LS3_JSON_BIT_MTIME,
LS3_JSON_BIT_CTIME,
+ LS3_JSON_BIT_CRTIME,
LS3_JSON_BIT_SIZE,
LS3_JSON_BIT_BLOCKS,
LS3_JSON_BIT_FILE_FID,
LS3_JSON_ATTR_ATIME = 1U << LS3_JSON_BIT_ATIME,
LS3_JSON_ATTR_MTIME = 1U << LS3_JSON_BIT_MTIME,
LS3_JSON_ATTR_CTIME = 1U << LS3_JSON_BIT_CTIME,
+ LS3_JSON_ATTR_CRTIME = 1U << LS3_JSON_BIT_CRTIME,
LS3_JSON_ATTR_SIZE = 1U << LS3_JSON_BIT_SIZE,
LS3_JSON_ATTR_BLOCKS = 1U << LS3_JSON_BIT_BLOCKS,
LS3_JSON_ATTR_FILE_FID = 1U << LS3_JSON_BIT_FILE_FID,
int64_t loa_atime;
int64_t loa_mtime;
int64_t loa_ctime;
+ int64_t loa_crtime;
int64_t loa_size;
int64_t loa_mode;
int64_t loa_blocks; /* number of 512B blocks. */
loa->loa_atime = inode_time(inode->i_atime, inode->i_atime_extra);
loa->loa_mtime = inode_time(inode->i_mtime, inode->i_mtime_extra);
loa->loa_ctime = inode_time(inode->i_ctime, inode->i_ctime_extra);
- /* crtime? */
+ loa->loa_crtime = inode_time(inode->i_crtime, inode->i_crtime_extra);
loa->loa_size = EXT2_I_SIZE(inode);
loa->loa_mode = inode->i_mode; /* __u16 */
loa->loa_uid = inode_uid(*inode);
lipe_scan3_format "$device" '(self-fid)'
lipe_scan3_format "$device" '(ino)'
- for proc in ino atime blocks ctime self-fid file-fid flags gid mode mtime nlink projid size uid; do
+ for proc in ino atime blocks crtime ctime self-fid file-fid flags gid mode mtime nlink projid size uid; do
expect_print lipe_scan3_format "$device" "($proc)"
done
- for proc in absolute-paths relative-paths links lov-pools lov-ost-indexes xattrs; do
+ for proc in absolute-paths relative-paths links lov-mirror-count lov-ost-indexes lov-pools lov-stripe-count xattrs; do
expect_print lipe_scan3_format "$device" "($proc)"
done
}
init_lipe_scan3_env "$file"
+ expect_expr "$device" '(positive? (crtime))' '#t'
+
time=$(stat --format=%X $file) # atime
expect_attr "$device" atime "$time"
}
run_test 130 "lipe_scan3 lov-pools and lov-ost-indexes do the right thing"
+test_131() {
+ local facet=mds1
+ local device="$(facet_device $facet)"
+ local file=$MOUNT/$tfile
+
+ init_lipe_scan3_env "$file"
+ expect_expr "$device" '(lov-mirror-count)' 0
+ expect_expr "$device" '(lov-stripe-count)' 0
+
+ $LFS setstripe -c 2 "$file"
+ sync
+
+ expect_expr "$device" '(lov-mirror-count)' 1
+ expect_expr "$device" '(lov-stripe-count)' 2
+
+ echo XXX > "$file"
+ $LFS mirror extend -N -c 4 "$file"
+ sync
+
+ expect_expr "$device" '(lov-mirror-count)' 2
+ expect_expr "$device" '(lov-stripe-count)' 4
+}
+run_test 131 "lipe_scan3 lov-mirror-count and lov-stripe-count do the right thing"
+
test_200() {
local facet=mds1
local device="$(facet_device $facet)"