[[\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!\fR] \fB--foreign\fR [<\fItype\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--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--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]
[[\fB!\fR] \fB--mdt-hash\fR|\fB-H <\fIhashtype\fR>]
[[\fB!\fR] \fB--mirror-count|\fB-N\fR [\fB+-\fR]\fIn\fR]
[[\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>]
.BR --component-start | --comp-start
The file has component start offset \fIn\fR (in bytes) for any component.
.TP
+.BR --foreign
+File has a foreign (non-Lustre/free format) layout and is of the given
+.IR type ,
+if specified. Presently only
+.B none
+or
+.B daos
+are defined types, though 32-bit numeric types can also be used.
+.TP
.BR --gid | -g
File has specified numeric group ID.
.TP
Files that have the first data component on an MDT.
.RE
.TP
-.BR --foreign[=<type>]
-File is foreign (non-Lustre layout) and is of type if specified.
-Presently only none or daos are defined types.
-.RE
+.BR --lazy
+Use file size and blocks from MDT, if available, to avoid extra RPCs.
.TP
.BR --maxdepth
Limits find to decend at most \fIn\fR levels of directory tree.
Layout was created with the specified
.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.
--- /dev/null
+.so man3/llapi_get_lum_file_fd.3
--- /dev/null
+.so man3/llapi_get_lum_file_fd.3
--- /dev/null
+.so man3/llapi_get_lum_file_fd.3
--- /dev/null
+.TH llapi_get_lum_file_fd 3 "2019 July 15" "Lustre User API"
+.SH NAME
+llapi_get_lum_file_fd, llapi_get_lum_dir_fd, llapi_get_lum_file,
+llapi_get_lum_dir \- get valid file attrbutes and LOV stripe information to
+the user.
+
+.SH SYNOPSIS
+.nf
+.B #include <lustre/lustreapi.h>
+.PP
+.BI "int llapi_get_lum_file_fd(int " dir_fd ", const char *" fname ",
+.BI " __u64 *" valid ", lstatx_t *" statx ",
+.BI " struct lov_user_md *" lum ",
+.BI " size_t " lumsize ");"
+.PP
+.BI "int llapi_get_lum_dir_fd(int " dir_fd ", __u64 *" valid ",
+.BI " lstatx_t *" statx ", struct lov_user_md *" lum ",
+.BI " size_t " lumsize ");"
+.PP
+.BI "int llapi_get_lum_file(const char *" path ", __u64 *" valid ",
+.BI " lstatx_t *" statx ", struct lov_user_md *" lum ",
+.BI " size_t " lumsize ");"
+.PP
+.BI "int llapi_get_lum_dir(const char *" path ", __u64 *" valid ",
+.BI " lstatx_t *" statx ", struct lov_user_md *" lum ",
+.BI " size_t " lumsize ");"
+.fi
+.SH DESCRIPTION
+.PP
+The function
+.BR llapi_get_lum_file_fd() ,
+.BR llapi_get_lum_dir_fd() ,
+.BR llapi_get_lum_file() ,
+and
+.BR llapi_get_lum_dir()
+returns file attributes and LOV stripe information by an ioctl on the dir.
+.BR dir_fd
+is a file descriptor that refers to a directory. For function
+.BR llapi_get_lum_file_fd() ,
+if
+.BR fname
+is provided, it is a relative pathname that is interpreted relative to the
+directory referred to by
+.BR dir_fd .
+
+The function
+.BR llapi_get_lum_dir_fd() ,
+.BR llapi_get_lum_file() ,
+and
+.BR llapi_get_lum_dir()
+can be used for applications that are only processing a single file or directory
+referred to by
+.BR dir_fd
+or
+.BR path .
+
+The function
+.BR llapi_get_lum_file_fd()
+can be used for applications that process lots of files. It avoids opening,
+locking, and closing each file on the client if that is not needed. Multiple
+calls of this llapi can be done on the parent dir referenced by
+.B dir_fd
+with a single open for all files in that directory, and it also does not
+pollute the client dcache with millions of dentries when traversing a large
+filesystem.
+
+The stripe information for the target file is returned to the user in the
+.B struct lov_user_md
+pointed to by
+.BR lum
+if it is not a NULL pointer. The file attribute information for the target file
+is returned in the
+.BR lstatx_t
+structure pointed to by
+.BR statx
+if it is not a NULL pointer.
+The output argument
+.BR valid
+contains the flags to indicate which fields in the returned file attributes
+have been valid filled in.
+
+The valid flags are as follows:
+.TP
+OBD_MD_FLSIZE
+The returned file size is known strictly correct.
+.TP
+OBD_MD_FLBLOCKS
+The returned file blocks is known strictly correct.
+.TP
+OBD_MD_FLLAZYSIZE
+The returned file size is approximate, may never have been strictly correct.
+.TP
+OBD_MD_FLLAZYBLOCKS
+The returned file blocks is approximate, may never have been strictly correct.
+.TP
+OBD_MD_FLID
+The returned object ID is valid.
+.TP
+OBD_MD_FLATIME
+The returned access time is valid.
+.TP
+OBD_MD_FLMTIME
+The returned data modification time is valid.
+.TP
+OBD_MD_FLCTIME
+The returned change time is valid.
+.TP
+OBD_MD_FLBLKSZ
+The returned block size is valid.
+.TP
+OBD_MD_FLMODE
+The returned access bits (mode & ~S_IFMT) is valid.
+.TP
+OBD_MD_FLTYPE
+The returned object type (mode & S_IFMT) is valid.
+.TP
+OBD_MD_FLUID
+The returned user ID is vaild.
+.TP
+OBD_MD_FLGID
+The returned group ID is valid.
+.TP
+OBD_MD_FLFLAGS
+The returned flags word is valid.
+.TP
+OBD_MD_FLNLINK
+The returned link count is valid.
+.TP
+OBD_MD_FLRDEV
+The returned device number is valid.
+.SH RETURN VALUES
+.LP
+.BR llapi_get_lum_file_fd() ,
+.BR llapi_get_lum_dir_fd() ,
+.BR llapi_get_lum_file() ,
+and
+.BR llapi_get_lum_dir()
+return 0 on success or a negative errno value on failure.
+.SH ERRORS
+.TP 15
+.SM -ENOMEM
+Insufficient memory to complete operation.
+.TP
+.SM -EFAULT
+Memory region is not properly mapped.
+.TP
+.SM -EINVAL
+One or more invalid arguments are given.
+.TP
+.SM -EOPNOTSUPP
+The operation is not supported.
+.TP
+.SM -ENOTTY
+File does not reside on a Lustre filesystem.
+.TP
+.SM -ENOENT
+.I path
+does not exist.
+.TP
+.SM -EBADF
+.I dir_fd
+is not a valid open file descriptor.
+.SH "SEE ALSO"
+.BR lustreapi (7)
fp_check_foreign:1,
fp_exclude_foreign:1,
fp_check_ext_size:1, /* extension size */
- fp_exclude_ext_size:1;
+ fp_exclude_ext_size:1,
+ fp_lazy:1;
enum llapi_layout_verbose fp_verbose;
int fp_quiet;
int llapi_path2fid(const char *path, struct lu_fid *fid);
int llapi_get_mdt_index_by_fid(int fd, const struct lu_fid *fid,
int *mdt_index);
+int llapi_get_lum_file(const char *path, __u64 *valid, lstatx_t *statx,
+ struct lov_user_md *lum, size_t lumsize);
+int llapi_get_lum_dir(const char *path, __u64 *valid, lstatx_t *statx,
+ struct lov_user_md *lum, size_t lumsize);
+int llapi_get_lum_file_fd(int dir_fd, const char *fname, __u64 *valid,
+ lstatx_t *statx, struct lov_user_md *lum,
+ size_t lumsize);
+int llapi_get_lum_dir_fd(int dir_fd, __u64 *valid, lstatx_t *statx,
+ struct lov_user_md *lum, size_t lumsize);
+
int llapi_fd2fid(int fd, struct lu_fid *fid);
/* get FID of parent dir + the related name of entry in this parent dir */
int llapi_path2parent(const char *path, unsigned int linkno,
#define OBD_MD_FLPROJID (0x0100000000000000ULL) /* project ID */
#define OBD_MD_SECCTX (0x0200000000000000ULL) /* embed security xattr */
+#define OBD_MD_FLLAZYSIZE (0x0400000000000000ULL) /* Lazy size */
+#define OBD_MD_FLLAZYBLOCKS (0x0800000000000000ULL) /* Lazy blocks */
+
#define OBD_MD_FLALLQUOTA (OBD_MD_FLUSRQUOTA | \
OBD_MD_FLGRPQUOTA | \
OBD_MD_FLPRJQUOTA)
#define fstatat_f fstatat
#endif
+#ifndef STATX_BASIC_STATS
+/*
+ * Timestamp structure for the timestamps in struct statx.
+ *
+ * tv_sec holds the number of seconds before (negative) or after (positive)
+ * 00:00:00 1st January 1970 UTC.
+ *
+ * tv_nsec holds a number of nanoseconds (0..999,999,999) after the tv_sec time.
+ *
+ * __reserved is held in case we need a yet finer resolution.
+ */
+struct statx_timestamp {
+ __s64 tv_sec;
+ __u32 tv_nsec;
+ __s32 __reserved;
+};
+
+/*
+ * Structures for the extended file attribute retrieval system call
+ * (statx()).
+ *
+ * The caller passes a mask of what they're specifically interested in as a
+ * parameter to statx(). What statx() actually got will be indicated in
+ * st_mask upon return.
+ *
+ * For each bit in the mask argument:
+ *
+ * - if the datum is not supported:
+ *
+ * - the bit will be cleared, and
+ *
+ * - the datum will be set to an appropriate fabricated value if one is
+ * available (eg. CIFS can take a default uid and gid), otherwise
+ *
+ * - the field will be cleared;
+ *
+ * - otherwise, if explicitly requested:
+ *
+ * - the datum will be synchronised to the server if AT_STATX_FORCE_SYNC is
+ * set or if the datum is considered out of date, and
+ *
+ * - the field will be filled in and the bit will be set;
+ *
+ * - otherwise, if not requested, but available in approximate form without any
+ * effort, it will be filled in anyway, and the bit will be set upon return
+ * (it might not be up to date, however, and no attempt will be made to
+ * synchronise the internal state first);
+ *
+ * - otherwise the field and the bit will be cleared before returning.
+ *
+ * Items in STATX_BASIC_STATS may be marked unavailable on return, but they
+ * will have values installed for compatibility purposes so that stat() and
+ * co. can be emulated in userspace.
+ */
+struct statx {
+ /* 0x00 */
+ __u32 stx_mask; /* What results were written [uncond] */
+ __u32 stx_blksize; /* Preferred general I/O size [uncond] */
+ __u64 stx_attributes; /* Flags conveying information about the file [uncond] */
+ /* 0x10 */
+ __u32 stx_nlink; /* Number of hard links */
+ __u32 stx_uid; /* User ID of owner */
+ __u32 stx_gid; /* Group ID of owner */
+ __u16 stx_mode; /* File mode */
+ __u16 __spare0[1];
+ /* 0x20 */
+ __u64 stx_ino; /* Inode number */
+ __u64 stx_size; /* File size */
+ __u64 stx_blocks; /* Number of 512-byte blocks allocated */
+ __u64 stx_attributes_mask; /* Mask to show what's supported in stx_attributes */
+ /* 0x40 */
+ struct statx_timestamp stx_atime; /* Last access time */
+ struct statx_timestamp stx_btime; /* File creation time */
+ struct statx_timestamp stx_ctime; /* Last attribute change time */
+ struct statx_timestamp stx_mtime; /* Last data modification time */
+ /* 0x80 */
+ __u32 stx_rdev_major; /* Device ID of special file [if bdev/cdev] */
+ __u32 stx_rdev_minor;
+ __u32 stx_dev_major; /* ID of device containing file [uncond] */
+ __u32 stx_dev_minor;
+ /* 0x90 */
+ __u64 __spare2[14]; /* Spare space for future expansion */
+ /* 0x100 */
+};
+
+/*
+ * Flags to be stx_mask
+ *
+ * Query request/result mask for statx() and struct statx::stx_mask.
+ *
+ * These bits should be set in the mask argument of statx() to request
+ * particular items when calling statx().
+ */
+#define STATX_TYPE 0x00000001U /* Want/got stx_mode & S_IFMT */
+#define STATX_MODE 0x00000002U /* Want/got stx_mode & ~S_IFMT */
+#define STATX_NLINK 0x00000004U /* Want/got stx_nlink */
+#define STATX_UID 0x00000008U /* Want/got stx_uid */
+#define STATX_GID 0x00000010U /* Want/got stx_gid */
+#define STATX_ATIME 0x00000020U /* Want/got stx_atime */
+#define STATX_MTIME 0x00000040U /* Want/got stx_mtime */
+#define STATX_CTIME 0x00000080U /* Want/got stx_ctime */
+#define STATX_INO 0x00000100U /* Want/got stx_ino */
+#define STATX_SIZE 0x00000200U /* Want/got stx_size */
+#define STATX_BLOCKS 0x00000400U /* Want/got stx_blocks */
+#define STATX_BASIC_STATS 0x000007ffU /* The stuff in the normal stat struct */
+#define STATX_BTIME 0x00000800U /* Want/got stx_btime */
+#define STATX_ALL 0x00000fffU /* All currently supported flags */
+#define STATX__RESERVED 0x80000000U /* Reserved for future struct statx expansion */
+
+/*
+ * Attributes to be found in stx_attributes and masked in stx_attributes_mask.
+ *
+ * These give information about the features or the state of a file that might
+ * be of use to ordinary userspace programs such as GUIs or ls rather than
+ * specialised tools.
+ *
+ * Note that the flags marked [I] correspond to generic FS_IOC_FLAGS
+ * semantically. Where possible, the numerical value is picked to correspond
+ * also.
+ */
+#define STATX_ATTR_COMPRESSED 0x00000004 /* [I] File is compressed by the fs */
+#define STATX_ATTR_IMMUTABLE 0x00000010 /* [I] File is marked immutable */
+#define STATX_ATTR_APPEND 0x00000020 /* [I] File is append-only */
+#define STATX_ATTR_NODUMP 0x00000040 /* [I] File is not to be dumped */
+#define STATX_ATTR_ENCRYPTED 0x00000800 /* [I] File requires key to decrypt in fs */
+
+#define STATX_ATTR_AUTOMOUNT 0x00001000 /* Dir: Automount trigger */
+
+#endif
+
+typedef struct statx lstatx_t;
+
#define HAVE_LOV_USER_MDS_DATA
#define LUSTRE_EOF 0xffffffffffffffffULL
#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 *)
+#ifdef HAVE_LOV_USER_MDS_DATA
+#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)
+#endif
#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 {
+ struct lu_fid lmd_fid; /* Lustre FID */
+ lstatx_t lmd_stx; /* MDS statx struct */
+ __u64 lmd_flags; /* MDS stat flags */
+ __u32 lmd_lmmsize; /* LOV EA size */
+ __u32 lmd_padding; /* unused */
+ struct lov_user_md_v1 lmd_lmm; /* LOV EA 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;
+ lstatx_t __user *stxp = NULL;
+ __u64 __user *flagsp = NULL;
+ __u32 __user *lmmsizep = NULL;
+ struct lu_fid __user *fidp = 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;
- }
+ fidp = &lmdp->lmd_fid;
+ stxp = &lmdp->lmd_stx;
+ flagsp = &lmdp->lmd_flags;
+ lmmsizep = &lmdp->lmd_lmmsize;
+ 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_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)))
- GOTO(out_req, rc = -EFAULT);
- }
+ if (copy_to_user(statp, &st, sizeof(st)))
+ GOTO(out_req, rc = -EFAULT);
+ } else if (cmd == IOC_MDC_GETFILEINFO ||
+ cmd == LL_IOC_MDC_GETINFO) {
+ lstatx_t stx = { 0 };
+ __u64 valid = body->mbo_valid;
+
+ stx.stx_blksize = PAGE_SIZE;
+ stx.stx_nlink = body->mbo_nlink;
+ stx.stx_uid = body->mbo_uid;
+ stx.stx_gid = body->mbo_gid;
+ stx.stx_mode = body->mbo_mode;
+ stx.stx_ino = cl_fid_build_ino(&body->mbo_fid1,
+ sbi->ll_flags &
+ LL_SBI_32BIT_API);
+ stx.stx_size = body->mbo_size;
+ stx.stx_blocks = body->mbo_blocks;
+ stx.stx_atime.tv_sec = body->mbo_atime;
+ stx.stx_ctime.tv_sec = body->mbo_ctime;
+ stx.stx_mtime.tv_sec = body->mbo_mtime;
+ stx.stx_rdev_major = MAJOR(body->mbo_rdev);
+ stx.stx_rdev_minor = MINOR(body->mbo_rdev);
+ stx.stx_dev_major = MAJOR(inode->i_sb->s_dev);
+ stx.stx_dev_minor = MINOR(inode->i_sb->s_dev);
+ stx.stx_mask |= STATX_BASIC_STATS;
- EXIT;
- out_req:
- ptlrpc_req_finished(request);
- if (filename)
- ll_putname(filename);
- return rc;
- }
+ /*
+ * For a striped directory, the size and blocks returned
+ * from MDT is not correct.
+ * The size and blocks are aggregated by client across
+ * all stripes.
+ * Thus for a striped directory, do not return the valid
+ * FLSIZE and FLBLOCKS flags to the caller.
+ * However, this whould be better decided by the MDS
+ * instead of the client.
+ */
+ if (cmd == LL_IOC_MDC_GETINFO &&
+ ll_i2info(inode)->lli_lsm_md != NULL)
+ valid &= ~(OBD_MD_FLSIZE | OBD_MD_FLBLOCKS);
+
+ if (flagsp && copy_to_user(flagsp, &valid,
+ sizeof(*flagsp)))
+ GOTO(out_req, rc = -EFAULT);
+
+ if (fidp && copy_to_user(fidp, &body->mbo_fid1,
+ sizeof(*fidp)))
+ GOTO(out_req, rc = -EFAULT);
+
+ if (!(valid & OBD_MD_FLSIZE))
+ stx.stx_mask &= ~STATX_SIZE;
+ if (!(valid & OBD_MD_FLBLOCKS))
+ stx.stx_mask &= ~STATX_BLOCKS;
+
+ if (stxp && copy_to_user(stxp, &stx, sizeof(stx)))
+ GOTO(out_req, rc = -EFAULT);
+
+ if (lmmsizep && copy_to_user(lmmsizep, &lmmsize,
+ sizeof(*lmmsizep)))
+ GOTO(out_req, rc = -EFAULT);
+ }
+
+ EXIT;
+out_req:
+ ptlrpc_req_finished(request);
+ if (filename)
+ ll_putname(filename);
+ return rc;
+ }
case OBD_IOC_QUOTACTL: {
struct if_quotactl *qctl;
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_FLLAZYSIZE | OBD_MD_FLLAZYBLOCKS;
+ b->mbo_size = ma->ma_som.ms_size;
+ b->mbo_blocks = ma->ma_som.ms_blocks;
}
}
- if (fid != NULL && (b->mbo_valid & OBD_MD_FLSIZE))
+ if (fid != NULL && (b->mbo_valid & OBD_MD_FLSIZE ||
+ b->mbo_valid & OBD_MD_FLLAZYSIZE))
CDEBUG(D_VFSTRACE, DFID": returning size %llu\n",
PFID(fid), (unsigned long long)b->mbo_size);
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 ] ||
}
run_test 56r "check lfs find -size works"
+test_56ra() {
+ local dir=$DIR/$tdir
+
+ [[ $OSC == "mdc" ]] && skip "DoM files" && return
+
+ setup_56 $dir $NUMFILES $NUMDIRS "-c 1"
+
+ cancel_lru_locks $OSC
+
+ local rpcs_before=$(calc_stats $OSC.*$OSC*.stats ldlm_glimpse_enqueue)
+ local expected=12
+ 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"
+
+ local rpcs_after=$(calc_stats $OSC.*$OSC*.stats ldlm_glimpse_enqueue)
+ [ $rpcs_before -eq $rpcs_after ] ||
+ error "'$cmd' should not send glimpse RPCs to OST"
+ cmd="$LFS find -size 0 -type f $dir"
+ nums=$($cmd | wc -l)
+ [ $nums -eq $expected ] ||
+ error "'$cmd' wrong: found $nums, expected $expected"
+ rpcs_after=$(calc_stats $OSC.*$OSC*.stats ldlm_glimpse_enqueue)
+ echo "Before: $rpcs_before After: $rpcs_after $NUMFILES"
+ $LCTL get_param osc.*.stats
+ [ $rpcs_after -eq $((rpcs_before + 12)) ] ||
+ error "'$cmd' should send 12 glimpse RPCs to OST"
+
+ cancel_lru_locks $OSC
+ rpcs_before=$(calc_stats $OSC.*$OSC*.stats ldlm_glimpse_enqueue)
+ 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"
+ rpcs_after=$(calc_stats $OSC.*$OSC*.stats ldlm_glimpse_enqueue)
+ $LCTL get_param mdc.*.stats
+ [ $rpcs_before -eq $rpcs_after ] ||
+ error "'$cmd' should not send glimpse RPCs to OST"
+ cmd="$LFS find ! -size 0 -type f $dir"
+ nums=$($cmd | wc -l)
+ [ $nums -eq $expected ] ||
+ error "'$cmd' wrong: found $nums, expected $expected"
+ rpcs_after=$(calc_stats $OSC.*$OSC*.stats ldlm_glimpse_enqueue)
+ echo "Before: $rpcs_before After: $rpcs_after $NUMFILES"
+ [ $rpcs_after -eq $((rpcs_before + 12)) ] ||
+ error "'$cmd' should send 12 glimpse RPCs to OST"
+
+ echo "test" > $dir/$tfile
+ echo "test2" > $dir/$tfile.2 && sync
+ cancel_lru_locks $OSC
+ rpcs_before=$(calc_stats $OSC.*$OSC*.stats ldlm_glimpse_enqueue)
+ 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"
+ rpcs_after=$(calc_stats $OSC.*$OSC*.stats ldlm_glimpse_enqueue)
+ [ $rpcs_before -eq $rpcs_after ] ||
+ error "'$cmd' should not send glimpse RPCs to OST"
+ cmd="$LFS find -size 5 -type f $dir"
+ nums=$($cmd | wc -l)
+ [ $nums -eq $expected ] ||
+ error "'$cmd' wrong: found $nums, expected $expected"
+ rpcs_after=$(calc_stats $OSC.*$OSC*.stats ldlm_glimpse_enqueue)
+ echo "Before: $rpcs_before After: $rpcs_after $NUMFILES"
+ [ $rpcs_after -eq $((rpcs_before + 14)) ] ||
+ error "'$cmd' should send 14 glimpse RPCs to OST"
+
+ cancel_lru_locks $OSC
+ rpcs_before=$(calc_stats $OSC.*$OSC*.stats ldlm_glimpse_enqueue)
+ 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"
+ rpcs_after=$(calc_stats $OSC.*$OSC*.stats ldlm_glimpse_enqueue)
+ [ $rpcs_before -eq $rpcs_after ] ||
+ error "'$cmd' should not send glimpse RPCs to OST"
+ cmd="$LFS find -size +5 -type f $dir"
+ nums=$($cmd | wc -l)
+ [ $nums -eq $expected ] ||
+ error "'$cmd' wrong: found $nums, expected $expected"
+ rpcs_after=$(calc_stats $OSC.*$OSC*.stats ldlm_glimpse_enqueue)
+ echo "Before: $rpcs_before After: $rpcs_after $NUMFILES"
+ [ $rpcs_after -eq $((rpcs_before + 14)) ] ||
+ error "'$cmd' should send 14 glimpse RPCs to OST"
+
+ cancel_lru_locks $OSC
+ rpcs_before=$(calc_stats $OSC.*$OSC*.stats ldlm_glimpse_enqueue)
+ 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"
+ rpcs_after=$(calc_stats $OSC.*$OSC*.stats ldlm_glimpse_enqueue)
+ [ $rpcs_before -eq $rpcs_after ] ||
+ error "'$cmd' should not send glimpse RPCs to OST"
+ cmd="$LFS find -size +0 -type f $dir"
+ nums=$($cmd | wc -l)
+ [ $nums -eq $expected ] ||
+ error "'$cmd' wrong: found $nums, expected $expected"
+ rpcs_after=$(calc_stats $OSC.*$OSC*.stats ldlm_glimpse_enqueue)
+ echo "Before: $rpcs_before After: $rpcs_after $NUMFILES"
+ [ $rpcs_after -eq $((rpcs_before + 14)) ] ||
+ error "'$cmd' should send 14 glimpse RPCs to OST"
+
+ cancel_lru_locks $OSC
+ rpcs_before=$(calc_stats $OSC.*$OSC*.stats ldlm_glimpse_enqueue)
+ 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"
+ rpcs_after=$(calc_stats $OSC.*$OSC*.stats ldlm_glimpse_enqueue)
+ [ $rpcs_before -eq $rpcs_after ] ||
+ error "'$cmd' should not send glimpse RPCs to OST"
+ cmd="$LFS find ! -size -5 -type f $dir"
+ nums=$($cmd | wc -l)
+ [ $nums -eq $expected ] ||
+ error "'$cmd' wrong: found $nums, expected $expected"
+ rpcs_after=$(calc_stats $OSC.*$OSC*.stats ldlm_glimpse_enqueue)
+ echo "Before: $rpcs_before After: $rpcs_after $NUMFILES"
+ [ $rpcs_after -eq $((rpcs_before + 14)) ] ||
+ error "'$cmd' should send 14 glimpse RPCs to OST"
+
+ cancel_lru_locks $OSC
+ rpcs_before=$(calc_stats $OSC.*$OSC*.stats ldlm_glimpse_enqueue)
+ 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"
+ rpcs_after=$(calc_stats $OSC.*$OSC*.stats ldlm_glimpse_enqueue)
+ [ $rpcs_before -eq $rpcs_after ] ||
+ error "'$cmd' should not send glimpse RPCs to OST"
+ cmd="$LFS find -size -5 -type f $dir"
+ nums=$($cmd | wc -l)
+ [ $nums -eq $expected ] ||
+ error "'$cmd' wrong: found $nums, expected $expected"
+ rpcs_after=$(calc_stats $OSC.*$OSC*.stats ldlm_glimpse_enqueue)
+ echo "Before: $rpcs_before After: $rpcs_after $NUMFILES"
+ [ $rpcs_after -eq $((rpcs_before + 14)) ] ||
+ error "'$cmd' should send 14 glimpse RPCs to OST"
+}
+run_test 56ra "check lfs find -size -lazy works for data on OSTs"
+
test_56s() { # LU-611 #LU-9369
[[ $OSTCOUNT -lt 2 ]] && skip_env "need at least 2 OSTs"
done
check_lsom_size $DIR/$tfile $size
- # multi-client wirtes
+ # multi-client writes
num=$(get_node_count ${CLIENTS//,/ })
size=$(($num * $bs))
offset=0
{ .val = 'i', .name = "stripe_index", .has_arg = required_argument},
{ .val = 'I', .name = "comp-id", .has_arg = required_argument},
{ .val = 'I', .name = "component-id", .has_arg = required_argument},
+/* find { .val = 'l', .name = "lazy", .has_arg = no_argument }, */
{ .val = 'L', .name = "layout", .has_arg = required_argument },
{ .val = 'm', .name = "mdt", .has_arg = required_argument},
{ .val = 'm', .name = "mdt-index", .has_arg = required_argument},
{ .val = 'i', .name = "stripe-index", .has_arg = required_argument },
{ .val = 'i', .name = "stripe_index", .has_arg = required_argument },
/* getstripe { .val = 'I', .name = "comp-id", .has_arg = required_argument }*/
+ { .val = 'l', .name = "lazy", .has_arg = no_argument },
{ .val = 'L', .name = "layout", .has_arg = required_argument },
{ .val = 'm', .name = "mdt", .has_arg = required_argument },
{ .val = 'm', .name = "mdt-index", .has_arg = required_argument },
param.fp_check_hash_type = 1;
param.fp_exclude_hash_type = !!neg_opt;
break;
+ case 'l':
+ param.fp_lazy = 1;
+ break;
case 'L':
ret = name2layout(¶m.fp_layout, optarg);
if (ret)
param.fp_check_ext_size = 1;
param.fp_exclude_ext_size = !!neg_opt;
break;
+ default:
+ ret = CMD_HELP;
+ goto err;
+ };
+ }
- default:
- ret = CMD_HELP;
- goto err;
- };
- }
-
- if (pathstart == -1) {
- fprintf(stderr, "error: %s: no filename|pathname\n",
- argv[0]);
- ret = CMD_HELP;
- goto err;
- } else if (pathend == -1) {
- /* no options */
- pathend = argc;
- }
+ if (pathstart == -1) {
+ fprintf(stderr, "error: %s: no filename|pathname\n",
+ argv[0]);
+ ret = CMD_HELP;
+ goto err;
+ } else if (pathend == -1) {
+ /* no options */
+ pathend = argc;
+ }
do {
rc = llapi_find(argv[pathstart], ¶m);
{ .val = 'i', .name = "stripe_index", .has_arg = no_argument },
{ .val = 'I', .name = "comp-id", .has_arg = optional_argument },
{ .val = 'I', .name = "component-id", .has_arg = optional_argument },
+/* find { .val = 'l', .name = "lazy", .has_arg = no_argument }, */
{ .val = 'L', .name = "layout", .has_arg = no_argument },
{ .val = 'm', .name = "mdt", .has_arg = no_argument },
{ .val = 'm', .name = "mdt-index", .has_arg = no_argument },
{ .val = 'i', .name = "mdt-index", .has_arg = required_argument },
{ .val = 'i', .name = "mdt", .has_arg = required_argument },
#else
+/* find { .val = 'l', .name = "lazy", .has_arg = no_argument }, */
{ .val = 'm', .name = "mdt-index", .has_arg = required_argument },
{ .val = 'm', .name = "mdt", .has_arg = required_argument },
#endif
#include <sys/time.h>
#include <sys/types.h>
#include <sys/xattr.h>
+#include <sys/sysmacros.h>
#include <time.h>
#include <fnmatch.h>
#include <libgen.h> /* for dirname() */
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, offsetof(typeof(*param->fp_lmd), lmd_lmm) +
+ lum_size);
if (param->fp_lmd == NULL) {
llapi_error(LLAPI_MSG_ERROR, -ENOMEM,
- "error: allocation of %zu bytes for ioctl",
+ "error: allocate %zu bytes for layout failed",
sizeof(lstat_t) + param->fp_lum_size);
return -ENOMEM;
}
return ret;
}
-int get_lmd_info_fd(char *path, int parent_fd, int dir_fd,
+static void convert_lmd_statx(struct lov_user_mds_data *lmd_v2, lstat_t *st,
+ bool strict)
+{
+ memset(&lmd_v2->lmd_stx, 0, sizeof(lmd_v2->lmd_stx));
+ lmd_v2->lmd_stx.stx_blksize = st->st_blksize;
+ lmd_v2->lmd_stx.stx_nlink = st->st_nlink;
+ lmd_v2->lmd_stx.stx_uid = st->st_uid;
+ lmd_v2->lmd_stx.stx_gid = st->st_gid;
+ lmd_v2->lmd_stx.stx_mode = st->st_mode;
+ lmd_v2->lmd_stx.stx_ino = st->st_ino;
+ lmd_v2->lmd_stx.stx_size = st->st_size;
+ lmd_v2->lmd_stx.stx_blocks = st->st_blocks;
+ lmd_v2->lmd_stx.stx_atime.tv_sec = st->st_atime;
+ lmd_v2->lmd_stx.stx_ctime.tv_sec = st->st_ctime;
+ lmd_v2->lmd_stx.stx_mtime.tv_sec = st->st_mtime;
+ lmd_v2->lmd_stx.stx_rdev_major = major(st->st_rdev);
+ lmd_v2->lmd_stx.stx_rdev_minor = minor(st->st_rdev);
+ lmd_v2->lmd_stx.stx_dev_major = major(st->st_dev);
+ lmd_v2->lmd_stx.stx_dev_minor = minor(st->st_dev);
+ lmd_v2->lmd_stx.stx_mask |= STATX_BASIC_STATS;
+
+ lmd_v2->lmd_flags = 0;
+ if (strict) {
+ lmd_v2->lmd_flags |= OBD_MD_FLSIZE | OBD_MD_FLBLOCKS;
+ } else {
+ lmd_v2->lmd_stx.stx_mask &= ~(STATX_SIZE | STATX_BLOCKS);
+ if (lmd_v2->lmd_stx.stx_size)
+ lmd_v2->lmd_flags |= OBD_MD_FLLAZYSIZE;
+ if (lmd_v2->lmd_stx.stx_blocks)
+ lmd_v2->lmd_flags |= OBD_MD_FLLAZYBLOCKS;
+ }
+ lmd_v2->lmd_flags |= OBD_MD_FLATIME | OBD_MD_FLMTIME | OBD_MD_FLCTIME |
+ OBD_MD_FLBLKSZ | OBD_MD_FLMODE | OBD_MD_FLTYPE |
+ OBD_MD_FLUID | OBD_MD_FLGID | OBD_MD_FLNLINK |
+ OBD_MD_FLRDEV;
+
+}
+
+static int convert_lmdbuf_v1v2(void *lmdbuf, int lmdlen)
+{
+ struct lov_user_mds_data_v1 *lmd_v1 = lmdbuf;
+ struct lov_user_mds_data *lmd_v2 = lmdbuf;
+ lstat_t st;
+ int size;
+
+ size = lov_comp_md_size((struct lov_comp_md_v1 *)&lmd_v1->lmd_lmm);
+ if (size < 0)
+ return size;
+
+ if (lmdlen < sizeof(lmd_v1->lmd_st) + size)
+ return -EOVERFLOW;
+
+ st = lmd_v1->lmd_st;
+ memmove(&lmd_v2->lmd_lmm, &lmd_v1->lmd_lmm,
+ lmdlen - (&lmd_v2->lmd_lmm - &lmd_v1->lmd_lmm));
+ convert_lmd_statx(lmd_v2, &st, false);
+ lmd_v2->lmd_lmmsize = 0;
+ lmd_v2->lmd_padding = 0;
+
+ return 0;
+}
+
+int get_lmd_info_fd(const 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, '/');
+ const char *fname = strrchr(path, '/');
/* IOC_MDC_GETFILEINFO takes as input the filename (relative to
* the parent directory) and returns struct lov_user_mds_data,
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) {
if (errno == ENOTTY) {
+ lstat_t st;
+
/* ioctl is not supported, it is not a lustre fs.
* Do the regular lstat(2) instead.
*/
- ret = lstat_f(path, st);
+ ret = lstat_f(path, &st);
if (ret) {
ret = -errno;
llapi_error(LLAPI_MSG_ERROR, ret,
"error: %s: lstat failed for %s",
__func__, path);
}
+
+ convert_lmd_statx(lmd, &st, true);
+ /* 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,
strcat(path, dent->d_name);
if (dent->d_type == DT_UNKNOWN) {
- lstat_t *st = ¶m->fp_lmd->lmd_st;
+ lstatx_t *stx = ¶m->fp_lmd->lmd_stx;
rc = get_lmd_info(path, d, NULL, param->fp_lmd,
param->fp_lum_size, GET_LMD_INFO);
if (rc == 0)
- dent->d_type = IFTODT(st->st_mode);
+ dent->d_type = IFTODT(stx->stx_mode);
else if (ret == 0)
ret = rc;
int lum_size = lov_user_md_size(is_dir ? 0 : lum->lmm_stripe_count,
lum->lmm_magic);
- new = malloc(sizeof(lstat_t) + lum_off + lum_size);
+ new = malloc(offsetof(typeof(*new), lmd_lmm) + lum_off + lum_size);
if (new == NULL) {
llapi_printf(LLAPI_MSG_NORMAL, "out of memory\n");
return new;
}
- memcpy(new, orig, sizeof(lstat_t));
+ memcpy(new, orig, sizeof(new->lmd_stx) + sizeof(new->lmd_flags)
+ + sizeof(new->lmd_lmmsize));
comp_v1 = (struct lov_comp_md_v1 *)&new->lmd_lmm;
comp_v1->lcm_magic = lum->lmm_magic;
*
* If 0 is returned, we need to do another RPC to the OSTs to obtain the
* updated timestamps. */
-static int find_time_check(lstat_t *st, struct find_param *param, int mds)
+static int find_time_check(lstatx_t *stx, struct find_param *param, int mds)
{
int rc = 1;
int rc2;
/* Check if file is accepted. */
if (param->fp_atime) {
- rc2 = find_value_cmp(st->st_atime, param->fp_atime,
+ rc2 = find_value_cmp(stx->stx_atime.tv_sec, param->fp_atime,
param->fp_asign, param->fp_exclude_atime,
param->fp_time_margin, mds);
if (rc2 < 0)
}
if (param->fp_mtime) {
- rc2 = find_value_cmp(st->st_mtime, param->fp_mtime,
+ rc2 = find_value_cmp(stx->stx_mtime.tv_sec, param->fp_mtime,
param->fp_msign, param->fp_exclude_mtime,
param->fp_time_margin, mds);
if (rc2 < 0)
}
if (param->fp_ctime) {
- rc2 = find_value_cmp(st->st_ctime, param->fp_ctime,
+ rc2 = find_value_cmp(stx->stx_ctime.tv_sec, param->fp_ctime,
param->fp_csign, param->fp_exclude_ctime,
param->fp_time_margin, mds);
if (rc2 < 0)
struct lov_user_ost_data_v1 *objects;
struct lov_comp_md_v1 *comp_v1 = NULL;
struct lov_user_md_v1 *v1 = ¶m->fp_lmd->lmd_lmm;
- lstat_t *st = ¶m->fp_lmd->lmd_st;
+ lstatx_t *stx = ¶m->fp_lmd->lmd_stx;
int i, j, k, count = 1;
if (param->fp_obd_uuid && param->fp_obd_index == OBD_NOT_FOUND)
return 0;
- if (!S_ISREG(st->st_mode))
+ if (!S_ISREG(stx->stx_mode))
return 0;
/* exclude foreign */
*/
static int find_check_foreign(struct find_param *param)
{
- if (S_ISREG(param->fp_lmd->lmd_st.st_mode)) {
+ if (S_ISREG(param->fp_lmd->lmd_stx.stx_mode)) {
struct lov_foreign_md *lfm;
lfm = (void *)¶m->fp_lmd->lmd_lmm;
}
}
- if (S_ISDIR(param->fp_lmd->lmd_st.st_mode)) {
+ if (S_ISDIR(param->fp_lmd->lmd_stx.stx_mode)) {
struct lmv_foreign_md *lfm;
lfm = (void *)param->fp_lmv_md;
static int find_check_comp_options(struct find_param *param)
{
- lstat_t *st = ¶m->fp_lmd->lmd_st;
+ lstatx_t *stx = ¶m->fp_lmd->lmd_stx;
struct lov_comp_md_v1 *comp_v1, *forged_v1 = NULL;
struct lov_user_md_v1 *v1 = ¶m->fp_lmd->lmd_lmm;
struct lov_comp_md_entry_v1 *entry;
comp_v1 = forged_v1;
comp_v1->lcm_entry_count = 1;
entry = &comp_v1->lcm_entries[0];
- entry->lcme_flags = S_ISDIR(st->st_mode) ? 0 : LCME_FL_INIT;
+ entry->lcme_flags = S_ISDIR(stx->stx_mode) ? 0 : LCME_FL_INIT;
entry->lcme_extent.e_start = 0;
entry->lcme_extent.e_end = LUSTRE_EOF;
}
struct find_param *param = (struct find_param *)data;
DIR *dir = dirp == NULL ? NULL : *dirp;
int decision = 1; /* 1 is accepted; -1 is rejected. */
- lstat_t *st = ¶m->fp_lmd->lmd_st;
+ lstatx_t *stx = ¶m->fp_lmd->lmd_stx;
int lustre_fs = 1;
int checked_type = 0;
int ret = 0;
__u32 stripe_count = 0;
+ __u64 flags;
int fd = -2;
if (parent == NULL && dir == NULL)
if (dir != NULL) {
ret = llapi_file_fget_mdtidx(dirfd(dir),
¶m->fp_file_mdt_index);
- } else if (S_ISREG(st->st_mode)) {
+ } else if (S_ISREG(stx->stx_mode)) {
/* FIXME: we could get the MDT index from the
* file's FID in lmd->lmd_lmm.lmm_oi without
* opening the file, once we are sure that
}
if (param->fp_type && !checked_type) {
- if ((st->st_mode & S_IFMT) == param->fp_type) {
+ if ((stx->stx_mode & S_IFMT) == param->fp_type) {
if (param->fp_exclude_type)
goto decided;
} else {
/* Prepare odb. */
if (param->fp_obd_uuid || param->fp_mdt_uuid) {
if (lustre_fs && param->fp_got_uuids &&
- param->fp_dev != st->st_dev) {
+ param->fp_dev != makedev(stx->stx_dev_major,
+ stx->stx_dev_minor)) {
/* A lustre/lustre mount point is crossed. */
param->fp_got_uuids = 0;
param->fp_obds_printed = 0;
if (ret)
goto out;
- param->fp_dev = st->st_dev;
+ param->fp_dev = makedev(stx->stx_dev_major,
+ stx->stx_dev_minor);
} else if (!lustre_fs && param->fp_got_uuids) {
/* A lustre/non-lustre mount point is crossed. */
param->fp_got_uuids = 0;
obd_matches:
if (param->fp_check_uid) {
- if (st->st_uid == param->fp_uid) {
+ if (stx->stx_uid == param->fp_uid) {
if (param->fp_exclude_uid)
goto decided;
} else {
}
if (param->fp_check_gid) {
- if (st->st_gid == param->fp_gid) {
+ if (stx->stx_gid == param->fp_gid) {
if (param->fp_exclude_gid)
goto decided;
} else {
int for_mds;
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;
- }
+ (S_ISREG(stx->stx_mode) && stripe_count) : 0;
+ decision = find_time_check(stx, 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'. */
+ flags = param->fp_lmd->lmd_flags;
+ if (param->fp_check_size &&
+ ((S_ISREG(stx->stx_mode) && stripe_count) ||
+ S_ISDIR(stx->stx_mode)) &&
+ !(flags & OBD_MD_FLSIZE ||
+ (param->fp_lazy && flags & OBD_MD_FLLAZYSIZE)))
+ 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(stx->stx_mode) && stripe_count) ||
+ S_ISDIR(stx->stx_mode)) &&
+ !(flags & OBD_MD_FLBLOCKS ||
+ (param->fp_lazy && flags & OBD_MD_FLLAZYBLOCKS)))
decision = 0;
+ /* 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 (!decision) {
+ lstat_t st;
+
/* For regular files with the stripe the decision may have not
* been taken yet if *time or size is to be checked. */
if (param->fp_obd_index != OBD_NOT_FOUND)
print_failed_tgt(param, path, LL_STATFS_LMV);
if (dir != NULL)
- ret = fstat_f(dirfd(dir), st);
+ ret = fstat_f(dirfd(dir), &st);
else if (de != NULL)
- ret = fstatat_f(dirfd(parent), de->d_name, st,
+ ret = fstatat_f(dirfd(parent), de->d_name, &st,
AT_SYMLINK_NOFOLLOW);
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 {
+ 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 {
ret = -errno;
llapi_error(LLAPI_MSG_ERROR, ret,
- "%s: IOC_LOV_GETINFO on %s failed",
+ "%s: stat on %s failed",
__func__, path);
goto out;
}
}
+ convert_lmd_statx(param->fp_lmd, &st, true);
/* Check the time on osc. */
- decision = find_time_check(st, param, 0);
+ decision = find_time_check(stx, param, 0);
if (decision == -1)
goto decided;
}
if (param->fp_check_size) {
- decision = find_value_cmp(st->st_size, param->fp_size,
+ decision = find_value_cmp(stx->stx_size, param->fp_size,
param->fp_size_sign,
param->fp_exclude_size,
param->fp_size_units, 0);
}
if (param->fp_check_blocks) { /* convert st_blocks to bytes */
- decision = find_value_cmp(st->st_blocks * 512, param->fp_blocks,
+ decision = find_value_cmp(stx->stx_blocks * 512,
+ param->fp_blocks,
param->fp_blocks_sign,
param->fp_exclude_blocks,
param->fp_blocks_units, 0);
__s32 data_fd;
const struct hsm_copytool_private *ct_priv;
struct hsm_copy copy;
- lstat_t stat;
+ lstatx_t statx;
};
enum ct_progress_type {
*/
static int ct_md_getattr(const struct hsm_copytool_private *ct,
const struct lu_fid *fid,
- lstat_t *st)
+ lstatx_t *stx)
{
struct lov_user_mds_data *lmd;
char fname[FID_NOBRACE_LEN + 1] = "";
if (rc >= sizeof(fname) || rc == 0)
return -EINVAL;
- lmd_size = sizeof(lmd->lmd_st) +
+ lmd_size = offsetof(typeof(*lmd), lmd_lmm) +
lov_user_md_size(LOV_MAX_STRIPE_COUNT, LOV_USER_MAGIC_V3);
- if (lmd_size < sizeof(lmd->lmd_st) + XATTR_SIZE_MAX)
- lmd_size = sizeof(lmd->lmd_st) + XATTR_SIZE_MAX;
+ if (lmd_size < offsetof(typeof(*lmd), lmd_lmm) + XATTR_SIZE_MAX)
+ lmd_size = offsetof(typeof(*lmd), lmd_lmm) + XATTR_SIZE_MAX;
lmd = malloc(lmd_size);
if (lmd == NULL)
if (rc)
goto out;
- *st = lmd->lmd_st;
+ *stx = lmd->lmd_stx;
out:
free(lmd);
if (fd < 0)
return fd;
- rc = fchown(fd, hcp->stat.st_uid, hcp->stat.st_gid);
+ rc = fchown(fd, hcp->statx.stx_uid, hcp->statx.stx_gid);
if (rc < 0)
goto err_cleanup;
hcp->source_fd = fd;
} else if (hai->hai_action == HSMA_RESTORE) {
- rc = ct_md_getattr(hcp->ct_priv, &hai->hai_fid, &hcp->stat);
+ rc = ct_md_getattr(hcp->ct_priv, &hai->hai_fid, &hcp->statx);
if (rc < 0)
goto err_out;
if (hai->hai_action == HSMA_RESTORE && errval == 0) {
struct ll_futimes_3 lfu = {
- .lfu_atime_sec = hcp->stat.st_atim.tv_sec,
- .lfu_atime_nsec = hcp->stat.st_atim.tv_nsec,
- .lfu_mtime_sec = hcp->stat.st_mtim.tv_sec,
- .lfu_mtime_nsec = hcp->stat.st_mtim.tv_nsec,
- .lfu_ctime_sec = hcp->stat.st_ctim.tv_sec,
- .lfu_ctime_nsec = hcp->stat.st_ctim.tv_nsec,
+ .lfu_atime_sec = hcp->statx.stx_atime.tv_sec,
+ .lfu_atime_nsec = hcp->statx.stx_atime.tv_nsec,
+ .lfu_mtime_sec = hcp->statx.stx_mtime.tv_sec,
+ .lfu_mtime_nsec = hcp->statx.stx_mtime.tv_nsec,
+ .lfu_ctime_sec = hcp->statx.stx_ctime.tv_sec,
+ .lfu_ctime_nsec = hcp->statx.stx_ctime.tv_nsec,
};
rc = fsync(hcp->data_fd);
return 0;
}
+int lov_comp_md_size(struct lov_comp_md_v1 *lcm)
+{
+ if (lcm->lcm_magic == LOV_MAGIC_V1 || lcm->lcm_magic == LOV_MAGIC_V3) {
+ struct lov_user_md *lum = (void *)lcm;
+
+ return lov_user_md_size(lum->lmm_stripe_count, lum->lmm_magic);
+ }
+
+ if (lcm->lcm_magic == LOV_MAGIC_FOREIGN) {
+ struct lov_foreign_md *lfm = (void *)lcm;
+
+ return lfm->lfm_length;
+ }
+
+ if (lcm->lcm_magic != LOV_MAGIC_COMP_V1)
+ return -EOPNOTSUPP;
+
+ return lcm->lcm_size;
+}
+
+int llapi_get_lum_file_fd(int dir_fd, const char *fname, __u64 *valid,
+ lstatx_t *statx, struct lov_user_md *lum,
+ size_t lumsize)
+{
+ struct lov_user_mds_data *lmd;
+ char buf[65536 + offsetof(typeof(*lmd), lmd_lmm)];
+ int parent_fd = -1;
+ int rc;
+
+ if (lum && lumsize < sizeof(*lum))
+ return -EINVAL;
+
+ /* If a file name is provided, it is relative to the parent directory */
+ if (fname) {
+ parent_fd = dir_fd;
+ dir_fd = -1;
+ }
+
+ lmd = (struct lov_user_mds_data *)buf;
+ rc = get_lmd_info_fd(fname, parent_fd, dir_fd, buf, sizeof(buf),
+ GET_LMD_INFO);
+ if (rc)
+ return rc;
+
+ *valid = lmd->lmd_flags;
+ if (statx)
+ memcpy(statx, &lmd->lmd_stx, sizeof(*statx));
+
+ if (lum) {
+ if (lmd->lmd_lmmsize > lumsize)
+ return -EOVERFLOW;
+ memcpy(lum, &lmd->lmd_lmm, lmd->lmd_lmmsize);
+ }
+
+ return 0;
+}
+
+int llapi_get_lum_dir_fd(int dir_fd, __u64 *valid, lstatx_t *statx,
+ struct lov_user_md *lum, size_t lumsize)
+{
+ return llapi_get_lum_file_fd(dir_fd, NULL, valid, statx, lum, lumsize);
+}
+
+int llapi_get_lum_file(const char *path, __u64 *valid, lstatx_t *statx,
+ struct lov_user_md *lum, size_t lumsize)
+{
+ char parent[PATH_MAX];
+ const char *fname;
+ char *tmp;
+ int offset;
+ int dir_fd;
+ int rc;
+
+ tmp = strrchr(path, '/');
+ if (!tmp) {
+ strncpy(parent, ".", sizeof(parent) - 1);
+ offset = -1;
+ } else {
+ strncpy(parent, path, tmp - path);
+ offset = tmp - path - 1;
+ parent[tmp - path] = 0;
+ }
+
+ fname = path;
+ if (offset >= 0)
+ fname += offset + 2;
+
+ dir_fd = open(parent, O_RDONLY);
+ if (dir_fd < 0) {
+ rc = -errno;
+ llapi_error(LLAPI_MSG_ERROR, rc, "cannot open '%s'", path);
+ return rc;
+ }
+
+ rc = llapi_get_lum_file_fd(dir_fd, fname, valid, statx, lum, lumsize);
+ close(dir_fd);
+ return rc;
+}
+
+int llapi_get_lum_dir(const char *path, __u64 *valid, lstatx_t *statx,
+ struct lov_user_md *lum, size_t lumsize)
+{
+ int dir_fd;
+ int rc;
+
+ dir_fd = open(path, O_RDONLY);
+ if (dir_fd < 0) {
+ rc = -errno;
+ llapi_error(LLAPI_MSG_ERROR, rc, "cannot open '%s'", path);
+ return rc;
+ }
+
+ rc = llapi_get_lum_dir_fd(dir_fd, valid, statx, lum, lumsize);
+ close(dir_fd);
+ return rc;
+}
GET_LMD_STRIPE = 2,
};
-int get_lmd_info_fd(char *path, int parentfd, int dirfd,
+int get_lmd_info_fd(const char *path, int parentfd, int dirfd,
void *lmd_buf, int lmd_len, enum get_lmd_info_type type);
+
+int lov_comp_md_size(struct lov_comp_md_v1 *lcm);
#endif /* _LUSTREAPI_INTERNAL_H_ */