Whamcloud - gitweb
LU-11367 som: integrate LSOM with lfs find 67/35167/22
authorQian Yingjin <qian@ddn.com>
Thu, 1 Nov 2018 08:49:53 +0000 (16:49 +0800)
committerOleg Drokin <green@whamcloud.com>
Fri, 20 Sep 2019 07:55:32 +0000 (07:55 +0000)
The patch integrates LSOM functionality with lfs find so that it
is possible to use LSOM functionality directly on the client. The
MDS fills in the mbo_size and mbo_blocks fields from the LSOM
xattr, if the actual size/blocks are not available, and then set
new OBD_MD_FLLSIZE and OBD_MD_FLLBLOCKS flags in the reply so that
the client knows these fields are valid.

The lfs find command adds "-l|--lazy" option to allow the use of
LSOM data from the MDS.

Add a new version of ioctl(LL_IOC_MDC_GETINFO) call that also returns
valid flags from the MDS RPC to userspace in struct lov_user_mds_data
so that it is possible to determine whether the size and blocks are
returned by the call.  The old LL_IOC_MDC_GETINFO ioctl number is
renamed to LL_IOC_MDC_GETINFO_OLD and is binary compatible, but
newly-compiled applications will use the new struct lov_user_mds_data.

New llapi interfaces llapi_get_lum_file(), llapi_get_lum_dir(),
llapi_get_lum_file_fd(), llapi_get_lum_dir_fd() are added to fetch
valid stat() attributes and LOV info to the user.

Signed-off-by: Qian Yingjin <qian@ddn.com>
Signed-off-by: Andreas Dilger <adilger@whamcloud.com>
Change-Id: I21dfae7c2633dead5d83b438ec340fea4d3ebbe5
Reviewed-on: https://review.whamcloud.com/35167
Tested-by: jenkins <devops@whamcloud.com>
Tested-by: Maloo <maloo@whamcloud.com>
Reviewed-by: Li Xi <lixi@ddn.com>
17 files changed:
lustre/doc/lfs-find.1
lustre/doc/llapi_get_lum_dir.3 [new file with mode: 0644]
lustre/doc/llapi_get_lum_dir_fd.3 [new file with mode: 0644]
lustre/doc/llapi_get_lum_file.3 [new file with mode: 0644]
lustre/doc/llapi_get_lum_file_fd.3 [new file with mode: 0644]
lustre/include/lustre/lustreapi.h
lustre/include/uapi/linux/lustre/lustre_idl.h
lustre/include/uapi/linux/lustre/lustre_user.h
lustre/llite/dir.c
lustre/mdt/mdt_handler.c
lustre/mdt/mdt_som.c
lustre/tests/sanity.sh [changed mode: 0644->0755]
lustre/utils/lfs.c
lustre/utils/liblustreapi.c
lustre/utils/liblustreapi_hsm.c
lustre/utils/liblustreapi_layout.c
lustre/utils/lustreapi_internal.h

index cfba95d..041869d 100644 (file)
@@ -14,8 +14,11 @@ lfs-find \- Lustre client utility to list files with specific attributes
       [[\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!\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--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]
@@ -24,7 +27,6 @@ lfs-find \- Lustre client utility to list files with specific attributes
 [[\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--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>]
 [\fB--print\fR|\fB-P\fR]
       [\fB--print0\fR|\fB-0\fR]
 [[\fB!\fR] \fB--projid\fR |<\fIprojid\fR>]
@@ -104,6 +106,15 @@ local on the network to clients.
 .BR --component-start | --comp-start
 The file has component start offset \fIn\fR (in bytes) for any component.
 .TP
 .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
 .BR --gid | -g
 File has specified numeric group ID.
 .TP
@@ -124,10 +135,8 @@ HSM-archived files that are not resident in the filesystem.
 Files that have the first data component on an MDT.
 .RE
 .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.
 .TP
 .BR --maxdepth
 Limits find to decend at most \fIn\fR levels of directory tree.
@@ -199,16 +208,6 @@ and replacement using
 Layout was created with the specified
 .I pool
 name.  For composite files, this may match the pool of any component.
 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.
 .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.
diff --git a/lustre/doc/llapi_get_lum_dir.3 b/lustre/doc/llapi_get_lum_dir.3
new file mode 100644 (file)
index 0000000..fc97dde
--- /dev/null
@@ -0,0 +1 @@
+.so man3/llapi_get_lum_file_fd.3
diff --git a/lustre/doc/llapi_get_lum_dir_fd.3 b/lustre/doc/llapi_get_lum_dir_fd.3
new file mode 100644 (file)
index 0000000..fc97dde
--- /dev/null
@@ -0,0 +1 @@
+.so man3/llapi_get_lum_file_fd.3
diff --git a/lustre/doc/llapi_get_lum_file.3 b/lustre/doc/llapi_get_lum_file.3
new file mode 100644 (file)
index 0000000..fc97dde
--- /dev/null
@@ -0,0 +1 @@
+.so man3/llapi_get_lum_file_fd.3
diff --git a/lustre/doc/llapi_get_lum_file_fd.3 b/lustre/doc/llapi_get_lum_file_fd.3
new file mode 100644 (file)
index 0000000..46699d4
--- /dev/null
@@ -0,0 +1,164 @@
+.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)
index 32e1ca1..17b19f8 100644 (file)
@@ -273,7 +273,8 @@ struct find_param {
                                 fp_check_foreign:1,
                                 fp_exclude_foreign:1,
                                 fp_check_ext_size:1, /* extension size */
                                 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;
 
        enum llapi_layout_verbose fp_verbose;
        int                      fp_quiet;
@@ -403,6 +404,16 @@ int llapi_fid2path(const char *device, const char *fidstr, char *path,
 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_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,
 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,
index 372d0de..36b5571 100644 (file)
@@ -1309,6 +1309,9 @@ lov_mds_md_max_stripe_count(size_t buf_size, __u32 lmm_magic)
 #define OBD_MD_FLPROJID      (0x0100000000000000ULL) /* project ID */
 #define OBD_MD_SECCTX        (0x0200000000000000ULL) /* embed security xattr */
 
 #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 OBD_MD_FLALLQUOTA (OBD_MD_FLUSRQUOTA | \
                           OBD_MD_FLGRPQUOTA | \
                           OBD_MD_FLPRJQUOTA)
index b799e71..a71d6f8 100644 (file)
@@ -113,6 +113,138 @@ typedef struct stat     lstat_t;
 #define fstatat_f       fstatat
 #endif
 
 #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 HAVE_LOV_USER_MDS_DATA
 
 #define LUSTRE_EOF 0xffffffffffffffffULL
@@ -521,11 +653,15 @@ struct fsxattr {
 #define LL_STATFS_LOV          2
 #define LL_STATFS_NODELAY      4
 
 #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 */
 
 
 #define MAX_OBD_NAME 128 /* If this changes, a NEW ioctl must be added */
 
@@ -822,11 +958,20 @@ static inline __u32 lov_user_md_size(__u16 stripes, __u32 lmm_magic)
  * 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
  * 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_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 {
 #endif
 
 struct lmv_user_mds_data {
index f3c86bc..61efdd5 100644 (file)
@@ -1660,38 +1660,48 @@ out_rmdir:
        case LL_IOC_LOV_GETSTRIPE:
        case LL_IOC_LOV_GETSTRIPE_NEW:
        case LL_IOC_MDC_GETINFO:
        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:
+       case IOC_MDC_GETFILEINFO_OLD:
        case IOC_MDC_GETFILESTRIPE: {
                struct ptlrpc_request *request = NULL;
                struct lov_user_md __user *lump;
        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);
                        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);
                }
 
                } 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 ||
 
                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;
                }
                        lmmsize = 0;
                        rc = 0;
                }
@@ -1703,11 +1713,23 @@ out_rmdir:
                    cmd == LL_IOC_LOV_GETSTRIPE ||
                    cmd == LL_IOC_LOV_GETSTRIPE_NEW) {
                        lump = (struct lov_user_md __user *)arg;
                    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;
                        struct lov_user_mds_data __user *lmdp;
+
                        lmdp = (struct lov_user_mds_data __user *)arg;
                        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
 
                if (lmmsize == 0) {
                        /* If the file has no striping then zero out *lump so
@@ -1720,9 +1742,9 @@ out_rmdir:
                        rc = -EOVERFLOW;
                }
 
                        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;
 
                        st.st_dev       = inode->i_sb->s_dev;
                        st.st_mode      = body->mbo_mode;
@@ -1740,18 +1762,74 @@ out_rmdir:
                                                sbi->ll_flags &
                                                LL_SBI_32BIT_API);
 
                                                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;
 
        case OBD_IOC_QUOTACTL: {
                 struct if_quotactl *qctl;
 
index 520609c..6db4735 100644 (file)
@@ -801,10 +801,15 @@ void mdt_pack_attr2body(struct mdt_thread_info *info, struct mdt_body *b,
                        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;
                        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);
 
                CDEBUG(D_VFSTRACE, DFID": returning size %llu\n",
                       PFID(fid), (unsigned long long)b->mbo_size);
 
index fa3f033..80438fa 100644 (file)
@@ -85,21 +85,21 @@ int mdt_get_som(struct mdt_thread_info *info, struct mdt_object *obj,
 
                ma->ma_valid |= MA_SOM;
 
 
                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_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.
                         */
 
                        /*
                         * 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;
                        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;
                }
        } else if (rc == -ENODATA) {
                rc = 0;
old mode 100644 (file)
new mode 100755 (executable)
index 8ddd5fc..335aac4
@@ -5785,39 +5785,73 @@ test_56r() {
        setup_56 $dir $NUMFILES $NUMDIRS
 
        local expected=12
        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"
        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
        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"
        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
        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"
        cmd="$LFS find -size 5 -type f $dir"
        nums=$($cmd | wc -l)
        [ $nums -eq $expected ] ||
                error "'$cmd' wrong: found $nums, expected $expected"
+
        expected=1
        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"
        cmd="$LFS find -size +5 -type f $dir"
        nums=$($cmd | wc -l)
        [ $nums -eq $expected ] ||
                error "'$cmd' wrong: found $nums, expected $expected"
+
        expected=2
        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"
        cmd="$LFS find -size +0 -type f $dir"
        nums=$($cmd | wc -l)
        [ $nums -eq $expected ] ||
                error "'$cmd' wrong: found $nums, expected $expected"
+
        expected=2
        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"
        cmd="$LFS find ! -size -5 -type f $dir"
        nums=$($cmd | wc -l)
        [ $nums -eq $expected ] ||
                error "'$cmd' wrong: found $nums, expected $expected"
+
        expected=12
        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 ] ||
        cmd="$LFS find -size -5 -type f $dir"
        nums=$($cmd | wc -l)
        [ $nums -eq $expected ] ||
@@ -5825,6 +5859,155 @@ test_56r() {
 }
 run_test 56r "check lfs find -size works"
 
 }
 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"
 
 test_56s() { # LU-611 #LU-9369
        [[ $OSTCOUNT -lt 2 ]] && skip_env "need at least 2 OSTs"
 
@@ -21718,7 +21901,7 @@ test_806() {
        done
        check_lsom_size $DIR/$tfile $size
 
        done
        check_lsom_size $DIR/$tfile $size
 
-       # multi-client wirtes
+       # multi-client writes
        num=$(get_node_count ${CLIENTS//,/ })
        size=$(($num * $bs))
        offset=0
        num=$(get_node_count ${CLIENTS//,/ })
        size=$(($num * $bs))
        offset=0
index a701711..924479f 100644 (file)
@@ -3078,6 +3078,7 @@ static int lfs_setstripe_internal(int argc, char **argv,
        { .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},
        { .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 = 'L',   .name = "layout",       .has_arg = required_argument },
        { .val = 'm',   .name = "mdt",          .has_arg = required_argument},
        { .val = 'm',   .name = "mdt-index",    .has_arg = required_argument},
@@ -4135,6 +4136,7 @@ static int lfs_find(int argc, char **argv)
        { .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 = '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 },
        { .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 },
@@ -4430,6 +4432,9 @@ static int lfs_find(int argc, char **argv)
                        param.fp_check_hash_type = 1;
                        param.fp_exclude_hash_type = !!neg_opt;
                        break;
                        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(&param.fp_layout, optarg);
                        if (ret)
                case 'L':
                        ret = name2layout(&param.fp_layout, optarg);
                        if (ret)
@@ -4706,22 +4711,21 @@ err_free:
                        param.fp_check_ext_size = 1;
                        param.fp_exclude_ext_size = !!neg_opt;
                        break;
                        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], &param);
 
        do {
                rc = llapi_find(argv[pathstart], &param);
@@ -4782,6 +4786,7 @@ static int lfs_getstripe_internal(int argc, char **argv,
        { .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 },
        { .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 = 'L',   .name = "layout",       .has_arg = no_argument },
        { .val = 'm',   .name = "mdt",          .has_arg = no_argument },
        { .val = 'm',   .name = "mdt-index",    .has_arg = no_argument },
@@ -5635,6 +5640,7 @@ static int lfs_setdirstripe(int argc, char **argv)
        { .val = 'i',   .name = "mdt-index",    .has_arg = required_argument },
        { .val = 'i',   .name = "mdt",          .has_arg = required_argument },
 #else
        { .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
        { .val = 'm',   .name = "mdt-index",    .has_arg = required_argument },
        { .val = 'm',   .name = "mdt",          .has_arg = required_argument },
 #endif
index 9a29475..3417c77 100644 (file)
@@ -59,6 +59,7 @@
 #include <sys/time.h>
 #include <sys/types.h>
 #include <sys/xattr.h>
 #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() */
 #include <time.h>
 #include <fnmatch.h>
 #include <libgen.h> /* for dirname() */
@@ -1797,10 +1798,11 @@ static int common_param_init(struct find_param *param, char *path)
                lum_size = PATH_MAX + 1;
 
        param->fp_lum_size = lum_size;
                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,
        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;
        }
                            sizeof(lstat_t) + param->fp_lum_size);
                return -ENOMEM;
        }
@@ -1909,11 +1911,74 @@ again:
        return ret;
 }
 
        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;
                    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)
        int ret = 0;
 
        if (parent_fd < 0 && dir_fd < 0)
@@ -1926,11 +1991,24 @@ int get_lmd_info_fd(char *path, int parent_fd, int dir_fd,
                 * and returns struct lov_user_mds_data, while
                 * LL_IOC_LOV_GETSTRIPE returns only struct lov_user_md.
                 */
                 * 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) {
        } 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,
 
                /* IOC_MDC_GETFILEINFO takes as input the filename (relative to
                 * the parent directory) and returns struct lov_user_mds_data,
@@ -1950,24 +2028,48 @@ int get_lmd_info_fd(char *path, int parent_fd, int dir_fd,
                        errno = -ret;
                else if (ret >= lmdlen || ret++ == 0)
                        errno = EINVAL;
                        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) {
        }
 
        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.
                         */
                        /* 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);
                        }
                        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,
                } else if (errno == ENOENT) {
                        ret = -errno;
                        llapi_error(LLAPI_MSG_WARN, ret,
@@ -2049,12 +2151,12 @@ static int llapi_semantic_traverse(char *path, int size, DIR *parent,
                strcat(path, dent->d_name);
 
                if (dent->d_type == DT_UNKNOWN) {
                strcat(path, dent->d_name);
 
                if (dent->d_type == DT_UNKNOWN) {
-                       lstat_t *st = &param->fp_lmd->lmd_st;
+                       lstatx_t *stx = &param->fp_lmd->lmd_stx;
 
                        rc = get_lmd_info(path, d, NULL, param->fp_lmd,
                                          param->fp_lum_size, GET_LMD_INFO);
                        if (rc == 0)
 
                        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;
 
                        else if (ret == 0)
                                ret = rc;
 
@@ -3604,13 +3706,14 @@ struct lov_user_mds_data *lov_forge_comp_v1(struct lov_user_mds_data *orig,
        int lum_size = lov_user_md_size(is_dir ? 0 : lum->lmm_stripe_count,
                                        lum->lmm_magic);
 
        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;
        }
 
        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;
 
        comp_v1 = (struct lov_comp_md_v1 *)&new->lmd_lmm;
        comp_v1->lcm_magic = lum->lmm_magic;
@@ -3881,14 +3984,14 @@ int llapi_file_lookup(int dirfd, const char *name)
  *
  * If 0 is returned, we need to do another RPC to the OSTs to obtain the
  * updated timestamps. */
  *
  * 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) {
 {
        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)
                                     param->fp_asign, param->fp_exclude_atime,
                                     param->fp_time_margin, mds);
                if (rc2 < 0)
@@ -3897,7 +4000,7 @@ static int find_time_check(lstat_t *st, struct find_param *param, int mds)
        }
 
        if (param->fp_mtime) {
        }
 
        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)
                                     param->fp_msign, param->fp_exclude_mtime,
                                     param->fp_time_margin, mds);
                if (rc2 < 0)
@@ -3910,7 +4013,7 @@ static int find_time_check(lstat_t *st, struct find_param *param, int mds)
        }
 
        if (param->fp_ctime) {
        }
 
        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)
                                     param->fp_csign, param->fp_exclude_ctime,
                                     param->fp_time_margin, mds);
                if (rc2 < 0)
@@ -3935,13 +4038,13 @@ static int check_obd_match(struct find_param *param)
        struct lov_user_ost_data_v1 *objects;
        struct lov_comp_md_v1 *comp_v1 = NULL;
        struct lov_user_md_v1 *v1 = &param->fp_lmd->lmd_lmm;
        struct lov_user_ost_data_v1 *objects;
        struct lov_comp_md_v1 *comp_v1 = NULL;
        struct lov_user_md_v1 *v1 = &param->fp_lmd->lmd_lmm;
-       lstat_t *st = &param->fp_lmd->lmd_st;
+       lstatx_t *stx = &param->fp_lmd->lmd_stx;
        int i, j, k, count = 1;
 
        if (param->fp_obd_uuid && param->fp_obd_index == OBD_NOT_FOUND)
                return 0;
 
        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 */
                return 0;
 
        /* exclude foreign */
@@ -4176,7 +4279,7 @@ static int find_check_layout(struct find_param *param)
  */
 static int find_check_foreign(struct find_param *param)
 {
  */
 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 *)&param->fp_lmd->lmd_lmm;
                struct lov_foreign_md *lfm;
 
                lfm = (void *)&param->fp_lmd->lmd_lmm;
@@ -4192,7 +4295,7 @@ static int find_check_foreign(struct find_param *param)
                }
        }
 
                }
        }
 
-       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;
                struct lmv_foreign_md *lfm;
 
                lfm = (void *)param->fp_lmv_md;
@@ -4254,7 +4357,7 @@ static int find_check_pool(struct find_param *param)
 
 static int find_check_comp_options(struct find_param *param)
 {
 
 static int find_check_comp_options(struct find_param *param)
 {
-       lstat_t *st = &param->fp_lmd->lmd_st;
+       lstatx_t *stx = &param->fp_lmd->lmd_stx;
        struct lov_comp_md_v1 *comp_v1, *forged_v1 = NULL;
        struct lov_user_md_v1 *v1 = &param->fp_lmd->lmd_lmm;
        struct lov_comp_md_entry_v1 *entry;
        struct lov_comp_md_v1 *comp_v1, *forged_v1 = NULL;
        struct lov_user_md_v1 *v1 = &param->fp_lmd->lmd_lmm;
        struct lov_comp_md_entry_v1 *entry;
@@ -4272,7 +4375,7 @@ static int find_check_comp_options(struct find_param *param)
                comp_v1 = forged_v1;
                comp_v1->lcm_entry_count = 1;
                entry = &comp_v1->lcm_entries[0];
                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;
        }
                entry->lcme_extent.e_start = 0;
                entry->lcme_extent.e_end = LUSTRE_EOF;
        }
@@ -4400,11 +4503,12 @@ static int cb_find_init(char *path, DIR *parent, DIR **dirp,
        struct find_param *param = (struct find_param *)data;
        DIR *dir = dirp == NULL ? NULL : *dirp;
        int decision = 1; /* 1 is accepted; -1 is rejected. */
        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 = &param->fp_lmd->lmd_st;
+       lstatx_t *stx = &param->fp_lmd->lmd_stx;
        int lustre_fs = 1;
        int checked_type = 0;
        int ret = 0;
        __u32 stripe_count = 0;
        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)
        int fd = -2;
 
        if (parent == NULL && dir == NULL)
@@ -4489,7 +4593,7 @@ static int cb_find_init(char *path, DIR *parent, DIR **dirp,
                        if (dir != NULL) {
                                ret = llapi_file_fget_mdtidx(dirfd(dir),
                                                     &param->fp_file_mdt_index);
                        if (dir != NULL) {
                                ret = llapi_file_fget_mdtidx(dirfd(dir),
                                                     &param->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
                                /* 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
@@ -4523,7 +4627,7 @@ static int cb_find_init(char *path, DIR *parent, DIR **dirp,
        }
 
        if (param->fp_type && !checked_type) {
        }
 
        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 {
                        if (param->fp_exclude_type)
                                goto decided;
                } else {
@@ -4535,7 +4639,8 @@ static int cb_find_init(char *path, DIR *parent, DIR **dirp,
         /* Prepare odb. */
        if (param->fp_obd_uuid || param->fp_mdt_uuid) {
                if (lustre_fs && param->fp_got_uuids &&
         /* 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;
                        /* A lustre/lustre mount point is crossed. */
                        param->fp_got_uuids = 0;
                        param->fp_obds_printed = 0;
@@ -4549,7 +4654,8 @@ static int cb_find_init(char *path, DIR *parent, DIR **dirp,
                        if (ret)
                                goto out;
 
                        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;
                } else if (!lustre_fs && param->fp_got_uuids) {
                        /* A lustre/non-lustre mount point is crossed. */
                        param->fp_got_uuids = 0;
@@ -4651,7 +4757,7 @@ static int cb_find_init(char *path, DIR *parent, DIR **dirp,
 
 obd_matches:
        if (param->fp_check_uid) {
 
 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_exclude_uid)
                                goto decided;
                } else {
@@ -4661,7 +4767,7 @@ obd_matches:
        }
 
        if (param->fp_check_gid) {
        }
 
        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 {
                        if (param->fp_exclude_gid)
                                goto decided;
                } else {
@@ -4716,21 +4822,34 @@ obd_matches:
                 int for_mds;
 
                for_mds = lustre_fs ?
                 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;
 
                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) {
        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)
                 /* 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)
@@ -4740,36 +4859,37 @@ obd_matches:
                         print_failed_tgt(param, path, LL_STATFS_LMV);
 
                if (dir != NULL)
                         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)
                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
                                        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,
                                ret = -errno;
                                llapi_error(LLAPI_MSG_ERROR, ret,
-                                           "%s: IOC_LOV_GETINFO on %s failed",
+                                           "%s: stat on %s failed",
                                            __func__, path);
                                goto out;
                        }
                }
 
                                            __func__, path);
                                goto out;
                        }
                }
 
+               convert_lmd_statx(param->fp_lmd, &st, true);
                /* Check the time on osc. */
                /* 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) {
                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);
                                          param->fp_size_sign,
                                          param->fp_exclude_size,
                                          param->fp_size_units, 0);
@@ -4778,7 +4898,8 @@ obd_matches:
        }
 
        if (param->fp_check_blocks) { /* convert st_blocks to bytes */
        }
 
        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);
                                          param->fp_blocks_sign,
                                          param->fp_exclude_blocks,
                                          param->fp_blocks_units, 0);
index c8a68ef..38e0fba 100644 (file)
@@ -81,7 +81,7 @@ struct hsm_copyaction_private {
        __s32                                    data_fd;
        const struct hsm_copytool_private       *ct_priv;
        struct hsm_copy                          copy;
        __s32                                    data_fd;
        const struct hsm_copytool_private       *ct_priv;
        struct hsm_copy                          copy;
-       lstat_t                                  stat;
+       lstatx_t                                 statx;
 };
 
 enum ct_progress_type {
 };
 
 enum ct_progress_type {
@@ -996,7 +996,7 @@ static int ct_open_by_fid(const struct hsm_copytool_private *ct,
  */
 static int ct_md_getattr(const struct hsm_copytool_private *ct,
                         const struct lu_fid *fid,
  */
 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] = "";
 {
        struct lov_user_mds_data *lmd;
        char fname[FID_NOBRACE_LEN + 1] = "";
@@ -1009,11 +1009,11 @@ static int ct_md_getattr(const struct hsm_copytool_private *ct,
        if (rc >= sizeof(fname) || rc == 0)
                return -EINVAL;
 
        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);
 
                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)
 
        lmd = malloc(lmd_size);
        if (lmd == NULL)
@@ -1024,7 +1024,7 @@ static int ct_md_getattr(const struct hsm_copytool_private *ct,
        if (rc)
                goto out;
 
        if (rc)
                goto out;
 
-       *st = lmd->lmd_st;
+       *stx = lmd->lmd_stx;
 out:
        free(lmd);
 
 out:
        free(lmd);
 
@@ -1060,7 +1060,7 @@ static int create_restore_volatile(struct hsm_copyaction_private *hcp,
        if (fd < 0)
                return fd;
 
        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;
 
        if (rc < 0)
                goto err_cleanup;
 
@@ -1130,7 +1130,7 @@ int llapi_hsm_action_begin(struct hsm_copyaction_private **phcp,
 
                hcp->source_fd = fd;
        } else if (hai->hai_action == HSMA_RESTORE) {
 
                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 (rc < 0)
                        goto err_out;
 
@@ -1229,12 +1229,12 @@ int llapi_hsm_action_end(struct hsm_copyaction_private **phcp,
 
        if (hai->hai_action == HSMA_RESTORE && errval == 0) {
                struct ll_futimes_3 lfu = {
 
        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);
                };
 
                rc = fsync(hcp->data_fd);
index d88deb3..e47b303 100644 (file)
@@ -3313,3 +3313,119 @@ int llapi_layout_dom_size(struct llapi_layout *layout, uint64_t *size)
        return 0;
 }
 
        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;
+}
index c0662b4..f69fca0 100644 (file)
@@ -163,6 +163,8 @@ enum get_lmd_info_type {
        GET_LMD_STRIPE = 2,
 };
 
        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);
                    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_ */
 #endif /* _LUSTREAPI_INTERNAL_H_ */