[[\fB!\fR] \fB--component-start|\fB--comp-start\fR [\fB+-\fR]\fIn\fR[\fBKMGTPE\fR]]
[[\fB!\fR] \fB--gid\fR|\fB-g\fR|\fB--group\fR|\fB-G\fR <\fIgname\fR>|<\fIgid\fR>]
[[\fB!\fR] \fB--layout\fR|\fB-L mdt\fR,\fBraid0\fR,\fBreleased\fR]
+[\fB--lazy\fR|\fB-z\fR]
[\fB--maxdepth\fR|\fB-D\fI n\fR]
[[\fB!\fR] \fB--mdt\fR|\fB--mdt-index\fR|\fB-m\fR <\fIuuid\fR|\fIindex\fR,...>]
[[\fB!\fR] \fB--mdt-count\fR|\fB-T\fR [\fB+-\fR]\fIn\fR]
Files that have the first data component on an MDT.
.RE
.TP
+.BR --lazy | -z
+Use LSOM xattr as file size and blocks if LSOM is valid.
+.TP
.BR --maxdepth
Limits find to decend at most \fIn\fR levels of directory tree.
.TP
fp_exclude_hash_type:1,
fp_yaml:1, /* output layout in YAML */
fp_check_blocks:1,
- fp_exclude_blocks:1;
+ fp_exclude_blocks:1,
+ fp_lazy:1;
enum llapi_layout_verbose fp_verbose;
int fp_quiet;
#define OBD_MD_FLPROJID (0x0100000000000000ULL) /* project ID */
#define OBD_MD_SECCTX (0x0200000000000000ULL) /* embed security xattr */
+#define OBD_MD_FLLSIZE (0x0200000000000000ULL) /* Lazy size */
+#define OBD_MD_FLLBLOCKS (0x0400000000000000ULL) /* Lazy blocks */
+
#define OBD_MD_FLALLQUOTA (OBD_MD_FLUSRQUOTA | \
OBD_MD_FLGRPQUOTA | \
OBD_MD_FLPRJQUOTA)
#define LL_STATFS_LOV 2
#define LL_STATFS_NODELAY 4
-#define IOC_MDC_TYPE 'i'
-#define IOC_MDC_LOOKUP _IOWR(IOC_MDC_TYPE, 20, struct obd_device *)
-#define IOC_MDC_GETFILESTRIPE _IOWR(IOC_MDC_TYPE, 21, struct lov_user_md *)
-#define IOC_MDC_GETFILEINFO _IOWR(IOC_MDC_TYPE, 22, struct lov_user_mds_data *)
-#define LL_IOC_MDC_GETINFO _IOWR(IOC_MDC_TYPE, 23, struct lov_user_mds_data *)
+#define IOC_MDC_TYPE 'i'
+#define IOC_MDC_LOOKUP _IOWR(IOC_MDC_TYPE, 20, struct obd_device *)
+#define IOC_MDC_GETFILESTRIPE _IOWR(IOC_MDC_TYPE, 21, struct lov_user_md *)
+#define IOC_MDC_GETFILEINFO_OLD _IOWR(IOC_MDC_TYPE, 22, struct lov_user_mds_data_v1 *)
+#define IOC_MDC_GETFILEINFO _IOWR(IOC_MDC_TYPE, 22, struct lov_user_mds_data)
+#define LL_IOC_MDC_GETINFO_OLD _IOWR(IOC_MDC_TYPE, 23, struct lov_user_mds_data_v1 *)
+#define LL_IOC_MDC_GETINFO _IOWR(IOC_MDC_TYPE, 23, struct lov_user_mds_data)
#define MAX_OBD_NAME 128 /* If this changes, a NEW ioctl must be added */
* use this. It is unsafe to #define those values in this header as it
* is possible the application has already #included <sys/stat.h>. */
#ifdef HAVE_LOV_USER_MDS_DATA
-#define lov_user_mds_data lov_user_mds_data_v1
+#define lov_user_mds_data lov_user_mds_data_v2
struct lov_user_mds_data_v1 {
lstat_t lmd_st; /* MDS stat struct */
struct lov_user_md_v1 lmd_lmm; /* LOV EA V1 user data */
} __attribute__((packed));
+
+struct lov_user_mds_data_v2 {
+ lstat_t lmd_st; /* MDS stat struct */
+ __u64 lmd_flags; /* MDS stat flags */
+ struct lov_user_md_v1 lmd_lmm; /* LOV EA V1 user data */
+} __attribute__((packed));
#endif
struct lmv_user_mds_data {
case LL_IOC_LOV_GETSTRIPE:
case LL_IOC_LOV_GETSTRIPE_NEW:
case LL_IOC_MDC_GETINFO:
+ case LL_IOC_MDC_GETINFO_OLD:
case IOC_MDC_GETFILEINFO:
+ case IOC_MDC_GETFILEINFO_OLD:
case IOC_MDC_GETFILESTRIPE: {
struct ptlrpc_request *request = NULL;
struct lov_user_md __user *lump;
- struct lov_mds_md *lmm = NULL;
- struct mdt_body *body;
- char *filename = NULL;
- int lmmsize;
-
- if (cmd == IOC_MDC_GETFILEINFO ||
- cmd == IOC_MDC_GETFILESTRIPE) {
+ struct lov_mds_md *lmm = NULL;
+ struct mdt_body *body;
+ char *filename = NULL;
+ lstat_t __user *statp = NULL;
+ __u64 __user *flags = NULL;
+ int lmmsize;
+
+ if (cmd == IOC_MDC_GETFILEINFO_OLD ||
+ cmd == IOC_MDC_GETFILEINFO ||
+ cmd == IOC_MDC_GETFILESTRIPE) {
filename = ll_getname((const char __user *)arg);
- if (IS_ERR(filename))
- RETURN(PTR_ERR(filename));
+ if (IS_ERR(filename))
+ RETURN(PTR_ERR(filename));
- rc = ll_lov_getstripe_ea_info(inode, filename, &lmm,
- &lmmsize, &request);
+ rc = ll_lov_getstripe_ea_info(inode, filename, &lmm,
+ &lmmsize, &request);
} else {
rc = ll_dir_getstripe(inode, (void **)&lmm, &lmmsize,
&request, 0);
}
- if (request) {
- body = req_capsule_server_get(&request->rq_pill,
- &RMF_MDT_BODY);
- LASSERT(body != NULL);
- } else {
- GOTO(out_req, rc);
- }
+ if (request) {
+ body = req_capsule_server_get(&request->rq_pill,
+ &RMF_MDT_BODY);
+ LASSERT(body != NULL);
+ } else {
+ GOTO(out_req, rc);
+ }
if (rc == -ENODATA && (cmd == IOC_MDC_GETFILEINFO ||
- cmd == LL_IOC_MDC_GETINFO)) {
+ cmd == LL_IOC_MDC_GETINFO ||
+ cmd == IOC_MDC_GETFILEINFO_OLD ||
+ cmd == LL_IOC_MDC_GETINFO_OLD)) {
lmmsize = 0;
rc = 0;
}
cmd == LL_IOC_LOV_GETSTRIPE ||
cmd == LL_IOC_LOV_GETSTRIPE_NEW) {
lump = (struct lov_user_md __user *)arg;
- } else {
+ } else if (cmd == IOC_MDC_GETFILEINFO_OLD ||
+ cmd == LL_IOC_MDC_GETINFO_OLD){
+ struct lov_user_mds_data_v1 __user *lmdp;
+
+ lmdp = (struct lov_user_mds_data_v1 __user *)arg;
+ statp = &lmdp->lmd_st;
+ lump = &lmdp->lmd_lmm;
+ } else {
struct lov_user_mds_data __user *lmdp;
+
lmdp = (struct lov_user_mds_data __user *)arg;
- lump = &lmdp->lmd_lmm;
- }
+ statp = &lmdp->lmd_st;
+ flags = &lmdp->lmd_flags;
+ lump = &lmdp->lmd_lmm;
+ }
if (lmmsize == 0) {
/* If the file has no striping then zero out *lump so
rc = -EOVERFLOW;
}
- if (cmd == IOC_MDC_GETFILEINFO || cmd == LL_IOC_MDC_GETINFO) {
- struct lov_user_mds_data __user *lmdp;
- lstat_t st = { 0 };
+ if (cmd == IOC_MDC_GETFILEINFO || cmd == LL_IOC_MDC_GETINFO ||
+ cmd == IOC_MDC_GETFILEINFO_OLD ||
+ cmd == LL_IOC_MDC_GETINFO_OLD) {
+ lstat_t st = { 0 };
st.st_dev = inode->i_sb->s_dev;
st.st_mode = body->mbo_mode;
sbi->ll_flags &
LL_SBI_32BIT_API);
- lmdp = (struct lov_user_mds_data __user *)arg;
- if (copy_to_user(&lmdp->lmd_st, &st, sizeof(st)))
+ if (copy_to_user(statp, &st, sizeof(st)))
GOTO(out_req, rc = -EFAULT);
+
+ if (cmd == IOC_MDC_GETFILEINFO ||
+ cmd == LL_IOC_MDC_GETINFO) {
+ __u64 valid = body->mbo_valid;
+
+ /*
+ * For a striped directory, do not return
+ * the valid FLSIZE and FLBLOCKS flags to
+ * the caller.
+ */
+ if (cmd == LL_IOC_MDC_GETINFO &&
+ ll_i2info(inode)->lli_lsm_md != NULL)
+ valid &= ~(OBD_MD_FLSIZE |
+ OBD_MD_FLBLOCKS);
+
+ if (flags && copy_to_user(flags, &valid,
+ sizeof(*flags)))
+ GOTO(out_req, rc = -EFAULT);
+ }
}
EXIT;
b->mbo_valid |= OBD_MD_FLSIZE | OBD_MD_FLBLOCKS;
} else if (info->mti_som_valid) { /* som is valid */
b->mbo_valid |= OBD_MD_FLSIZE | OBD_MD_FLBLOCKS;
+ } else if (ma->ma_valid & MA_SOM) { /* lsom is valid */
+ b->mbo_valid |= OBD_MD_FLLSIZE | OBD_MD_FLLBLOCKS;
+ b->mbo_size = ma->ma_som.ms_size;
+ b->mbo_blocks = ma->ma_som.ms_blocks;
}
}
ma->ma_valid |= MA_SOM;
- if ((som->ms_valid & SOM_FL_STRICT)) {
+ CDEBUG(D_INODE, DFID": Reading som attrs: "
+ "valid: %x, size: %lld, blocks: %lld\n",
+ PFID(mdt_object_fid(obj)), som->ms_valid,
+ som->ms_size, som->ms_blocks);
+
+ if (som->ms_valid & SOM_FL_STRICT) {
attr->la_valid |= LA_SIZE | LA_BLOCKS;
- attr->la_size = som->ms_size;
- attr->la_blocks = som->ms_blocks;
/*
* Size on MDS is valid and could be returned
* to client.
*/
+ attr->la_size = som->ms_size;
+ attr->la_blocks = som->ms_blocks;
info->mti_som_valid = 1;
-
- CDEBUG(D_INODE, DFID": Reading som attrs: "
- "valid: %x, size: %lld, blocks: %lld\n",
- PFID(mdt_object_fid(obj)), som->ms_valid,
- som->ms_size, som->ms_blocks);
}
} else if (rc == -ENODATA) {
rc = 0;
setup_56 $dir $NUMFILES $NUMDIRS
local expected=12
- local cmd="$LFS find -size 0 -type f $dir"
+ local cmd="$LFS find -size 0 -type f -lazy $dir"
local nums=$($cmd | wc -l)
[ $nums -eq $expected ] ||
error "'$cmd' wrong: found $nums, expected $expected"
+ cmd="$LFS find -size 0 -type f $dir"
+ nums=$($cmd | wc -l)
+ [ $nums -eq $expected ] ||
+ error "'$cmd' wrong: found $nums, expected $expected"
+
expected=0
+ cmd="$LFS find ! -size 0 -type f -lazy $dir"
+ nums=$($cmd | wc -l)
+ [ $nums -eq $expected ] ||
+ error "'$cmd' wrong: found $nums, expected $expected"
cmd="$LFS find ! -size 0 -type f $dir"
nums=$($cmd | wc -l)
[ $nums -eq $expected ] ||
error "'$cmd' wrong: found $nums, expected $expected"
+
echo "test" > $dir/$tfile
echo "test2" > $dir/$tfile.2 && sync
expected=1
+ cmd="$LFS find -size 5 -type f -lazy $dir"
+ nums=$($cmd | wc -l)
+ [ $nums -eq $expected ] ||
+ error "'$cmd' wrong: found $nums, expected $expected"
cmd="$LFS find -size 5 -type f $dir"
nums=$($cmd | wc -l)
[ $nums -eq $expected ] ||
error "'$cmd' wrong: found $nums, expected $expected"
+
expected=1
+ cmd="$LFS find -size +5 -type f -lazy $dir"
+ nums=$($cmd | wc -l)
+ [ $nums -eq $expected ] ||
+ error "'$cmd' wrong: found $nums, expected $expected"
cmd="$LFS find -size +5 -type f $dir"
nums=$($cmd | wc -l)
[ $nums -eq $expected ] ||
error "'$cmd' wrong: found $nums, expected $expected"
+
expected=2
+ cmd="$LFS find -size +0 -type f -lazy $dir"
+ nums=$($cmd | wc -l)
+ [ $nums -eq $expected ] ||
+ error "'$cmd' wrong: found $nums, expected $expected"
cmd="$LFS find -size +0 -type f $dir"
nums=$($cmd | wc -l)
[ $nums -eq $expected ] ||
error "'$cmd' wrong: found $nums, expected $expected"
+
expected=2
+ cmd="$LFS find ! -size -5 -type f -lazy $dir"
+ nums=$($cmd | wc -l)
+ [ $nums -eq $expected ] ||
+ error "'$cmd' wrong: found $nums, expected $expected"
cmd="$LFS find ! -size -5 -type f $dir"
nums=$($cmd | wc -l)
[ $nums -eq $expected ] ||
error "'$cmd' wrong: found $nums, expected $expected"
+
expected=12
+ cmd="$LFS find -size -5 -type f -lazy $dir"
+ nums=$($cmd | wc -l)
+ [ $nums -eq $expected ] ||
+ error "'$cmd' wrong: found $nums, expected $expected"
cmd="$LFS find -size -5 -type f $dir"
nums=$($cmd | wc -l)
[ $nums -eq $expected ] ||
{ .val = 'U', .name = "user", .has_arg = required_argument },
/* getstripe { .val = 'v', .name = "verbose", .has_arg = no_argument }, */
/* getstripe { .val = 'y', .name = "yaml", .has_arg = no_argument }, */
+ { .val = 'z', .name = "lazy", .has_arg = no_argument },
{ .name = NULL } };
int pathstart = -1;
int pathend = -1;
/* when getopt_long_only() hits '!' it returns 1, puts "!" in optarg */
while ((c = getopt_long_only(argc, argv,
- "-0A:b:c:C:D:E:g:G:H:i:L:m:M:n:N:O:Ppqrs:S:t:T:u:U:v",
+ "-0A:b:c:C:D:E:g:G:H:i:L:m:M:n:N:O:Ppqrs:S:t:T:u:U:vz",
long_opts, NULL)) >= 0) {
xtime = NULL;
xsign = NULL;
param.fp_check_mdt_count = 1;
param.fp_exclude_mdt_count = !!neg_opt;
break;
+ case 'z':
+ param.fp_lazy = 1;
+ break;
default:
ret = CMD_HELP;
goto err;
lum_size = PATH_MAX + 1;
param->fp_lum_size = lum_size;
- param->fp_lmd = calloc(1, sizeof(lstat_t) + lum_size);
+ param->fp_lmd = calloc(1, sizeof(lstat_t) + sizeof(__u64) + lum_size);
if (param->fp_lmd == NULL) {
llapi_error(LLAPI_MSG_ERROR, -ENOMEM,
"error: allocation of %zu bytes for ioctl",
return ret;
}
+static int convert_lmdbuf_v1v2(void *lmdbuf, int lmdlen)
+{ struct lov_user_mds_data *lmd = lmdbuf;
+ struct lov_user_mds_data_v1 *lmd_v1;
+ int offset;
+
+ lmd_v1 = malloc(lmdlen);
+ if (lmd_v1 == NULL) {
+ llapi_printf(LLAPI_MSG_ERROR, "out of memory\n");
+ return -ENOMEM;
+ }
+
+ memcpy(lmd_v1, lmdbuf, lmdlen);
+ lmd->lmd_flags = 0;
+ offset = sizeof(lstat_t) + sizeof(__u64);
+ memcpy((char *)lmdbuf + offset, &lmd_v1->lmd_lmm, lmdlen - offset);
+ free(lmd_v1);
+ return 0;
+}
+
int get_lmd_info_fd(char *path, int parent_fd, int dir_fd,
void *lmdbuf, int lmdlen, enum get_lmd_info_type type)
{
struct lov_user_mds_data *lmd = lmdbuf;
lstat_t *st = &lmd->lmd_st;
+ static bool use_old_ioctl;
+ unsigned long cmd;
int ret = 0;
if (parent_fd < 0 && dir_fd < 0)
* and returns struct lov_user_mds_data, while
* LL_IOC_LOV_GETSTRIPE returns only struct lov_user_md.
*/
- ret = ioctl(dir_fd, type == GET_LMD_INFO ? LL_IOC_MDC_GETINFO :
- LL_IOC_LOV_GETSTRIPE,
- lmdbuf);
+ if (type == GET_LMD_INFO)
+ cmd = use_old_ioctl ? LL_IOC_MDC_GETINFO_OLD :
+ LL_IOC_MDC_GETINFO;
+ else
+ cmd = LL_IOC_LOV_GETSTRIPE;
+
+retry_getinfo:
+ ret = ioctl(dir_fd, cmd, lmdbuf);
+ if (ret < 0 && errno == ENOTTY && cmd == LL_IOC_MDC_GETINFO) {
+ cmd = LL_IOC_MDC_GETINFO_OLD;
+ use_old_ioctl = true;
+ goto retry_getinfo;
+ }
+
+ if (cmd == LL_IOC_MDC_GETINFO_OLD && !ret)
+ ret = convert_lmdbuf_v1v2(lmdbuf, lmdlen);
} else if (parent_fd >= 0) {
char *fname = strrchr(path, '/');
errno = -ret;
else if (ret >= lmdlen || ret++ == 0)
errno = EINVAL;
- else
- ret = ioctl(parent_fd, type == GET_LMD_INFO ?
- IOC_MDC_GETFILEINFO :
- IOC_MDC_GETFILESTRIPE, lmdbuf);
+ else {
+ if (type == GET_LMD_INFO)
+ cmd = use_old_ioctl ? IOC_MDC_GETFILEINFO_OLD :
+ IOC_MDC_GETFILEINFO;
+ else
+ cmd = IOC_MDC_GETFILESTRIPE;
+
+retry_getfileinfo:
+ ret = ioctl(parent_fd, cmd, lmdbuf);
+ if (ret < 0 && errno == ENOTTY &&
+ cmd == IOC_MDC_GETFILEINFO) {
+ cmd = IOC_MDC_GETFILEINFO_OLD;
+ use_old_ioctl = true;
+ goto retry_getfileinfo;
+ }
+
+ if (cmd == IOC_MDC_GETFILEINFO_OLD && !ret)
+ ret = convert_lmdbuf_v1v2(lmdbuf, lmdlen);
+ }
}
if (ret && type == GET_LMD_INFO) {
"error: %s: lstat failed for %s",
__func__, path);
}
+
+ /* It may be wrong to set use_old_ioctl with true as
+ * the file is not a lustre fs. So reset it with false
+ * directly here.
+ */
+ use_old_ioctl = false;
} else if (errno == ENOENT) {
ret = -errno;
llapi_error(LLAPI_MSG_WARN, ret,
int checked_type = 0;
int ret = 0;
__u32 stripe_count = 0;
+ __u64 flags;
int fd = -2;
if (parent == NULL && dir == NULL)
for_mds = lustre_fs ?
(S_ISREG(st->st_mode) && stripe_count) : 0;
- decision = find_time_check(st, param, for_mds);
- if (decision == -1)
- goto decided;
- }
+ decision = find_time_check(st, param, for_mds);
+ if (decision == -1)
+ goto decided;
+ }
- /* If file still fits the request, ask ost for updated info.
- The regular stat is almost of the same speed as some new
- 'glimpse-size-ioctl'. */
+ /* If file still fits the request, ask ost for updated info.
+ * The regular stat is almost of the same speed as some new
+ * 'glimpse-size-ioctl'.
+ */
+
+ flags = param->fp_lmd->lmd_flags;
+ if (param->fp_check_size &&
+ ((S_ISREG(st->st_mode) && stripe_count) || S_ISDIR(st->st_mode)) &&
+ !(flags & OBD_MD_FLSIZE ||
+ (param->fp_lazy && flags & OBD_MD_FLLSIZE)))
+ decision = 0;
- if ((param->fp_check_size || param->fp_check_blocks) &&
- ((S_ISREG(st->st_mode) && stripe_count) || S_ISDIR(st->st_mode)))
+ if (param->fp_check_blocks &&
+ ((S_ISREG(st->st_mode) && stripe_count) || S_ISDIR(st->st_mode)) &&
+ !(flags & OBD_MD_FLBLOCKS ||
+ (param->fp_lazy && flags & OBD_MD_FLLBLOCKS)))
decision = 0;
if (!decision) {
else
ret = lstat_f(path, st);
- if (ret) {
- if (errno == ENOENT) {
- llapi_error(LLAPI_MSG_ERROR, -ENOENT,
- "warning: %s: %s does not exist",
- __func__, path);
- goto decided;
- } else {
+ if (ret) {
+ if (errno == ENOENT) {
+ llapi_error(LLAPI_MSG_ERROR, -ENOENT,
+ "warning: %s: %s does not exist",
+ __func__, path);
+ goto decided;
+ } else {
ret = -errno;
llapi_error(LLAPI_MSG_ERROR, ret,
- "%s: IOC_LOV_GETINFO on %s failed",
+ "%s: stat on %s failed",
__func__, path);
goto out;
}