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--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]
@@ -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--foreign\fR [<\fItype\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 --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
@@ -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
-.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.
@@ -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.
-.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.
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_exclude_ext_size:1;
+                                fp_exclude_ext_size:1,
+                                fp_lazy:1;
 
        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_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,
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_FLLAZYSIZE    (0x0400000000000000ULL) /* Lazy size */
+#define OBD_MD_FLLAZYBLOCKS  (0x0800000000000000ULL) /* Lazy blocks */
+
 #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
 
+#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
@@ -521,11 +653,15 @@ struct fsxattr {
 #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 */
 
@@ -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
-#define lov_user_mds_data lov_user_mds_data_v1
+#define lov_user_mds_data lov_user_mds_data_v2
 struct lov_user_mds_data_v1 {
        lstat_t lmd_st;                 /* MDS stat struct */
        struct lov_user_md_v1 lmd_lmm;  /* LOV EA V1 user data */
 } __attribute__((packed));
+
+struct lov_user_mds_data_v2 {
+       struct lu_fid lmd_fid;          /* Lustre FID */
+       lstatx_t lmd_stx;               /* MDS statx struct */
+       __u64 lmd_flags;                /* MDS stat flags */
+       __u32 lmd_lmmsize;              /* LOV EA size */
+       __u32 lmd_padding;              /* unused */
+       struct lov_user_md_v1 lmd_lmm;  /* LOV EA user data */
+} __attribute__((packed));
 #endif
 
 struct lmv_user_mds_data {
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_MDC_GETINFO_OLD:
        case IOC_MDC_GETFILEINFO:
+       case IOC_MDC_GETFILEINFO_OLD:
        case IOC_MDC_GETFILESTRIPE: {
                struct ptlrpc_request *request = NULL;
                struct lov_user_md __user *lump;
-                struct lov_mds_md *lmm = NULL;
-                struct mdt_body *body;
-                char *filename = NULL;
-                int lmmsize;
-
-                if (cmd == IOC_MDC_GETFILEINFO ||
-                    cmd == IOC_MDC_GETFILESTRIPE) {
+               struct lov_mds_md *lmm = NULL;
+               struct mdt_body *body;
+               char *filename = NULL;
+               lstat_t __user *statp = NULL;
+               lstatx_t __user *stxp = NULL;
+               __u64 __user *flagsp = NULL;
+               __u32 __user *lmmsizep = NULL;
+               struct lu_fid __user *fidp = NULL;
+               int lmmsize;
+
+               if (cmd == IOC_MDC_GETFILEINFO_OLD ||
+                   cmd == IOC_MDC_GETFILEINFO ||
+                   cmd == IOC_MDC_GETFILESTRIPE) {
                        filename = ll_getname((const char __user *)arg);
-                        if (IS_ERR(filename))
-                                RETURN(PTR_ERR(filename));
+                       if (IS_ERR(filename))
+                               RETURN(PTR_ERR(filename));
 
-                        rc = ll_lov_getstripe_ea_info(inode, filename, &lmm,
-                                                      &lmmsize, &request);
+                       rc = ll_lov_getstripe_ea_info(inode, filename, &lmm,
+                                                     &lmmsize, &request);
                } else {
                        rc = ll_dir_getstripe(inode, (void **)&lmm, &lmmsize,
                                              &request, 0);
                }
 
-                if (request) {
-                        body = req_capsule_server_get(&request->rq_pill,
-                                                      &RMF_MDT_BODY);
-                        LASSERT(body != NULL);
-                } else {
-                        GOTO(out_req, rc);
-                }
+               if (request) {
+                       body = req_capsule_server_get(&request->rq_pill,
+                                                     &RMF_MDT_BODY);
+                       LASSERT(body != NULL);
+               } else {
+                       GOTO(out_req, rc);
+               }
 
                if (rc == -ENODATA && (cmd == IOC_MDC_GETFILEINFO ||
-                                      cmd == LL_IOC_MDC_GETINFO)) {
+                                      cmd == LL_IOC_MDC_GETINFO ||
+                                      cmd == IOC_MDC_GETFILEINFO_OLD ||
+                                      cmd == LL_IOC_MDC_GETINFO_OLD)) {
                        lmmsize = 0;
                        rc = 0;
                }
@@ -1703,11 +1713,23 @@ out_rmdir:
                    cmd == LL_IOC_LOV_GETSTRIPE ||
                    cmd == LL_IOC_LOV_GETSTRIPE_NEW) {
                        lump = (struct lov_user_md __user *)arg;
-                } else {
+               } else if (cmd == IOC_MDC_GETFILEINFO_OLD ||
+                          cmd == LL_IOC_MDC_GETINFO_OLD){
+                       struct lov_user_mds_data_v1 __user *lmdp;
+
+                       lmdp = (struct lov_user_mds_data_v1 __user *)arg;
+                       statp = &lmdp->lmd_st;
+                       lump = &lmdp->lmd_lmm;
+               } else {
                        struct lov_user_mds_data __user *lmdp;
+
                        lmdp = (struct lov_user_mds_data __user *)arg;
-                        lump = &lmdp->lmd_lmm;
-                }
+                       fidp = &lmdp->lmd_fid;
+                       stxp = &lmdp->lmd_stx;
+                       flagsp = &lmdp->lmd_flags;
+                       lmmsizep = &lmdp->lmd_lmmsize;
+                       lump = &lmdp->lmd_lmm;
+               }
 
                if (lmmsize == 0) {
                        /* If the file has no striping then zero out *lump so
@@ -1720,9 +1742,9 @@ out_rmdir:
                        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;
@@ -1740,18 +1762,74 @@ out_rmdir:
                                                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;
 
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;
+               } 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);
 
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;
 
-               if ((som->ms_valid & SOM_FL_STRICT)) {
+               CDEBUG(D_INODE, DFID": Reading som attrs: "
+                      "valid: %x, size: %lld, blocks: %lld\n",
+                      PFID(mdt_object_fid(obj)), som->ms_valid,
+                      som->ms_size, som->ms_blocks);
+
+               if (som->ms_valid & SOM_FL_STRICT) {
                        attr->la_valid |= LA_SIZE | LA_BLOCKS;
-                       attr->la_size = som->ms_size;
-                       attr->la_blocks = som->ms_blocks;
 
                        /*
                         * Size on MDS is valid and could be returned
                         * to client.
                         */
+                       attr->la_size = som->ms_size;
+                       attr->la_blocks = som->ms_blocks;
                        info->mti_som_valid = 1;
-
-                       CDEBUG(D_INODE, DFID": Reading som attrs: "
-                              "valid: %x, size: %lld, blocks: %lld\n",
-                              PFID(mdt_object_fid(obj)), som->ms_valid,
-                              som->ms_size, som->ms_blocks);
                }
        } else if (rc == -ENODATA) {
                rc = 0;
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
-       local cmd="$LFS find -size 0 -type f $dir"
+       local cmd="$LFS find -size 0 -type f -lazy $dir"
        local nums=$($cmd | wc -l)
 
        [ $nums -eq $expected ] ||
                error "'$cmd' wrong: found $nums, expected $expected"
+       cmd="$LFS find -size 0 -type f $dir"
+       nums=$($cmd | wc -l)
+       [ $nums -eq $expected ] ||
+               error "'$cmd' wrong: found $nums, expected $expected"
+
        expected=0
+       cmd="$LFS find ! -size 0 -type f -lazy $dir"
+       nums=$($cmd | wc -l)
+       [ $nums -eq $expected ] ||
+               error "'$cmd' wrong: found $nums, expected $expected"
        cmd="$LFS find ! -size 0 -type f $dir"
        nums=$($cmd | wc -l)
        [ $nums -eq $expected ] ||
                error "'$cmd' wrong: found $nums, expected $expected"
+
        echo "test" > $dir/$tfile
        echo "test2" > $dir/$tfile.2 && sync
        expected=1
+       cmd="$LFS find -size 5 -type f -lazy $dir"
+       nums=$($cmd | wc -l)
+       [ $nums -eq $expected ] ||
+               error "'$cmd' wrong: found $nums, expected $expected"
        cmd="$LFS find -size 5 -type f $dir"
        nums=$($cmd | wc -l)
        [ $nums -eq $expected ] ||
                error "'$cmd' wrong: found $nums, expected $expected"
+
        expected=1
+       cmd="$LFS find -size +5 -type f -lazy $dir"
+       nums=$($cmd | wc -l)
+       [ $nums -eq $expected ] ||
+               error "'$cmd' wrong: found $nums, expected $expected"
        cmd="$LFS find -size +5 -type f $dir"
        nums=$($cmd | wc -l)
        [ $nums -eq $expected ] ||
                error "'$cmd' wrong: found $nums, expected $expected"
+
        expected=2
+       cmd="$LFS find -size +0 -type f -lazy $dir"
+       nums=$($cmd | wc -l)
+       [ $nums -eq $expected ] ||
+               error "'$cmd' wrong: found $nums, expected $expected"
        cmd="$LFS find -size +0 -type f $dir"
        nums=$($cmd | wc -l)
        [ $nums -eq $expected ] ||
                error "'$cmd' wrong: found $nums, expected $expected"
+
        expected=2
+       cmd="$LFS find ! -size -5 -type f -lazy $dir"
+       nums=$($cmd | wc -l)
+       [ $nums -eq $expected ] ||
+               error "'$cmd' wrong: found $nums, expected $expected"
        cmd="$LFS find ! -size -5 -type f $dir"
        nums=$($cmd | wc -l)
        [ $nums -eq $expected ] ||
                error "'$cmd' wrong: found $nums, expected $expected"
+
        expected=12
+       cmd="$LFS find -size -5 -type f -lazy $dir"
+       nums=$($cmd | wc -l)
+       [ $nums -eq $expected ] ||
+               error "'$cmd' wrong: found $nums, expected $expected"
        cmd="$LFS find -size -5 -type f $dir"
        nums=$($cmd | wc -l)
        [ $nums -eq $expected ] ||
@@ -5825,6 +5859,155 @@ test_56r() {
 }
 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"
 
@@ -21718,7 +21901,7 @@ test_806() {
        done
        check_lsom_size $DIR/$tfile $size
 
-       # multi-client wirtes
+       # multi-client writes
        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},
+/* 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},
@@ -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 = '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 },
@@ -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;
+               case 'l':
+                       param.fp_lazy = 1;
+                       break;
                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;
+               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);
@@ -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 },
+/* 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 },
@@ -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
+/* 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
index 9a29475..3417c77 100644 (file)
@@ -59,6 +59,7 @@
 #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() */
@@ -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;
-       param->fp_lmd = calloc(1, sizeof(lstat_t) + lum_size);
+       param->fp_lmd = calloc(1, offsetof(typeof(*param->fp_lmd), lmd_lmm) +
+                              lum_size);
        if (param->fp_lmd == NULL) {
                llapi_error(LLAPI_MSG_ERROR, -ENOMEM,
-                           "error: allocation of %zu bytes for ioctl",
+                           "error: allocate %zu bytes for layout failed",
                            sizeof(lstat_t) + param->fp_lum_size);
                return -ENOMEM;
        }
@@ -1909,11 +1911,74 @@ again:
        return ret;
 }
 
-int get_lmd_info_fd(char *path, int parent_fd, int dir_fd,
+static void convert_lmd_statx(struct lov_user_mds_data *lmd_v2, lstat_t *st,
+                             bool strict)
+{
+       memset(&lmd_v2->lmd_stx, 0, sizeof(lmd_v2->lmd_stx));
+       lmd_v2->lmd_stx.stx_blksize = st->st_blksize;
+       lmd_v2->lmd_stx.stx_nlink = st->st_nlink;
+       lmd_v2->lmd_stx.stx_uid = st->st_uid;
+       lmd_v2->lmd_stx.stx_gid = st->st_gid;
+       lmd_v2->lmd_stx.stx_mode = st->st_mode;
+       lmd_v2->lmd_stx.stx_ino = st->st_ino;
+       lmd_v2->lmd_stx.stx_size = st->st_size;
+       lmd_v2->lmd_stx.stx_blocks = st->st_blocks;
+       lmd_v2->lmd_stx.stx_atime.tv_sec = st->st_atime;
+       lmd_v2->lmd_stx.stx_ctime.tv_sec = st->st_ctime;
+       lmd_v2->lmd_stx.stx_mtime.tv_sec = st->st_mtime;
+       lmd_v2->lmd_stx.stx_rdev_major = major(st->st_rdev);
+       lmd_v2->lmd_stx.stx_rdev_minor = minor(st->st_rdev);
+       lmd_v2->lmd_stx.stx_dev_major = major(st->st_dev);
+       lmd_v2->lmd_stx.stx_dev_minor = minor(st->st_dev);
+       lmd_v2->lmd_stx.stx_mask |= STATX_BASIC_STATS;
+
+       lmd_v2->lmd_flags = 0;
+       if (strict) {
+               lmd_v2->lmd_flags |= OBD_MD_FLSIZE | OBD_MD_FLBLOCKS;
+       } else {
+               lmd_v2->lmd_stx.stx_mask &= ~(STATX_SIZE | STATX_BLOCKS);
+               if (lmd_v2->lmd_stx.stx_size)
+                       lmd_v2->lmd_flags |= OBD_MD_FLLAZYSIZE;
+               if (lmd_v2->lmd_stx.stx_blocks)
+                       lmd_v2->lmd_flags |= OBD_MD_FLLAZYBLOCKS;
+       }
+       lmd_v2->lmd_flags |= OBD_MD_FLATIME | OBD_MD_FLMTIME | OBD_MD_FLCTIME |
+                            OBD_MD_FLBLKSZ | OBD_MD_FLMODE | OBD_MD_FLTYPE |
+                            OBD_MD_FLUID | OBD_MD_FLGID | OBD_MD_FLNLINK |
+                            OBD_MD_FLRDEV;
+
+}
+
+static int convert_lmdbuf_v1v2(void *lmdbuf, int lmdlen)
+{
+       struct lov_user_mds_data_v1 *lmd_v1 = lmdbuf;
+       struct lov_user_mds_data *lmd_v2 = lmdbuf;
+       lstat_t st;
+       int size;
+
+       size = lov_comp_md_size((struct lov_comp_md_v1 *)&lmd_v1->lmd_lmm);
+       if (size < 0)
+               return size;
+
+       if (lmdlen < sizeof(lmd_v1->lmd_st) + size)
+               return -EOVERFLOW;
+
+       st = lmd_v1->lmd_st;
+       memmove(&lmd_v2->lmd_lmm, &lmd_v1->lmd_lmm,
+               lmdlen - (&lmd_v2->lmd_lmm - &lmd_v1->lmd_lmm));
+       convert_lmd_statx(lmd_v2, &st, false);
+       lmd_v2->lmd_lmmsize = 0;
+       lmd_v2->lmd_padding = 0;
+
+       return 0;
+}
+
+int get_lmd_info_fd(const char *path, int parent_fd, int dir_fd,
                    void *lmdbuf, int lmdlen, enum get_lmd_info_type type)
 {
        struct lov_user_mds_data *lmd = lmdbuf;
-       lstat_t *st = &lmd->lmd_st;
+       static bool use_old_ioctl;
+       unsigned long cmd;
        int ret = 0;
 
        if (parent_fd < 0 && dir_fd < 0)
@@ -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.
                 */
-               ret = ioctl(dir_fd, type == GET_LMD_INFO ? LL_IOC_MDC_GETINFO :
-                                                          LL_IOC_LOV_GETSTRIPE,
-                           lmdbuf);
+               if (type == GET_LMD_INFO)
+                       cmd = use_old_ioctl ? LL_IOC_MDC_GETINFO_OLD :
+                                             LL_IOC_MDC_GETINFO;
+               else
+                       cmd = LL_IOC_LOV_GETSTRIPE;
+
+retry_getinfo:
+               ret = ioctl(dir_fd, cmd, lmdbuf);
+               if (ret < 0 && errno == ENOTTY && cmd == LL_IOC_MDC_GETINFO) {
+                       cmd = LL_IOC_MDC_GETINFO_OLD;
+                       use_old_ioctl = true;
+                       goto retry_getinfo;
+               }
+
+               if (cmd == LL_IOC_MDC_GETINFO_OLD && !ret)
+                       ret = convert_lmdbuf_v1v2(lmdbuf, lmdlen);
        } else if (parent_fd >= 0) {
-               char *fname = strrchr(path, '/');
+               const char *fname = strrchr(path, '/');
 
                /* IOC_MDC_GETFILEINFO takes as input the filename (relative to
                 * the parent directory) and returns struct lov_user_mds_data,
@@ -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;
-               else
-                       ret = ioctl(parent_fd, type == GET_LMD_INFO ?
-                                               IOC_MDC_GETFILEINFO :
-                                               IOC_MDC_GETFILESTRIPE, lmdbuf);
+               else {
+                       if (type == GET_LMD_INFO)
+                               cmd = use_old_ioctl ? IOC_MDC_GETFILEINFO_OLD :
+                                                     IOC_MDC_GETFILEINFO;
+                       else
+                               cmd = IOC_MDC_GETFILESTRIPE;
+
+retry_getfileinfo:
+                       ret = ioctl(parent_fd, cmd, lmdbuf);
+                       if (ret < 0 && errno == ENOTTY &&
+                           cmd == IOC_MDC_GETFILEINFO) {
+                               cmd = IOC_MDC_GETFILEINFO_OLD;
+                               use_old_ioctl = true;
+                               goto retry_getfileinfo;
+                       }
+
+                       if (cmd == IOC_MDC_GETFILEINFO_OLD && !ret)
+                               ret = convert_lmdbuf_v1v2(lmdbuf, lmdlen);
+               }
        }
 
        if (ret && type == GET_LMD_INFO) {
                if (errno == ENOTTY) {
+                       lstat_t st;
+
                        /* ioctl is not supported, it is not a lustre fs.
                         * Do the regular lstat(2) instead.
                         */
-                       ret = lstat_f(path, st);
+                       ret = lstat_f(path, &st);
                        if (ret) {
                                ret = -errno;
                                llapi_error(LLAPI_MSG_ERROR, ret,
                                            "error: %s: lstat failed for %s",
                                            __func__, path);
                        }
+
+                       convert_lmd_statx(lmd, &st, true);
+                       /* It may be wrong to set use_old_ioctl with true as
+                        * the file is not a lustre fs. So reset it with false
+                        * directly here.
+                        */
+                       use_old_ioctl = false;
                } else if (errno == ENOENT) {
                        ret = -errno;
                        llapi_error(LLAPI_MSG_WARN, ret,
@@ -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) {
-                       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)
-                               dent->d_type = IFTODT(st->st_mode);
+                               dent->d_type = IFTODT(stx->stx_mode);
                        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);
 
-       new = malloc(sizeof(lstat_t) + lum_off + lum_size);
+       new = malloc(offsetof(typeof(*new), lmd_lmm) + lum_off + lum_size);
        if (new == NULL) {
                llapi_printf(LLAPI_MSG_NORMAL, "out of memory\n");
                return new;
        }
 
-       memcpy(new, orig, sizeof(lstat_t));
+       memcpy(new, orig, sizeof(new->lmd_stx) + sizeof(new->lmd_flags)
+              + sizeof(new->lmd_lmmsize));
 
        comp_v1 = (struct lov_comp_md_v1 *)&new->lmd_lmm;
        comp_v1->lcm_magic = lum->lmm_magic;
@@ -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. */
-static int find_time_check(lstat_t *st, struct find_param *param, int mds)
+static int find_time_check(lstatx_t *stx, struct find_param *param, int mds)
 {
        int rc = 1;
        int rc2;
 
        /* Check if file is accepted. */
        if (param->fp_atime) {
-               rc2 = find_value_cmp(st->st_atime, param->fp_atime,
+               rc2 = find_value_cmp(stx->stx_atime.tv_sec, param->fp_atime,
                                     param->fp_asign, param->fp_exclude_atime,
                                     param->fp_time_margin, mds);
                if (rc2 < 0)
@@ -3897,7 +4000,7 @@ static int find_time_check(lstat_t *st, struct find_param *param, int mds)
        }
 
        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)
@@ -3910,7 +4013,7 @@ static int find_time_check(lstat_t *st, struct find_param *param, int mds)
        }
 
        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)
@@ -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;
-       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;
 
-       if (!S_ISREG(st->st_mode))
+       if (!S_ISREG(stx->stx_mode))
                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)
 {
-       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;
@@ -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;
@@ -4254,7 +4357,7 @@ static int find_check_pool(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;
@@ -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];
-               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;
        }
@@ -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. */
-       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;
+       __u64 flags;
        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);
-                       } 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
@@ -4523,7 +4627,7 @@ static int cb_find_init(char *path, DIR *parent, DIR **dirp,
        }
 
        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 {
@@ -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 &&
-                   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;
@@ -4549,7 +4654,8 @@ static int cb_find_init(char *path, DIR *parent, DIR **dirp,
                        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;
@@ -4651,7 +4757,7 @@ static int cb_find_init(char *path, DIR *parent, DIR **dirp,
 
 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 {
@@ -4661,7 +4767,7 @@ obd_matches:
        }
 
        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 {
@@ -4716,21 +4822,34 @@ obd_matches:
                 int for_mds;
 
                for_mds = lustre_fs ?
-                       (S_ISREG(st->st_mode) && stripe_count) : 0;
-                decision = find_time_check(st, param, for_mds);
-                if (decision == -1)
-                        goto decided;
-        }
+                       (S_ISREG(stx->stx_mode) && stripe_count) : 0;
+               decision = find_time_check(stx, param, for_mds);
+               if (decision == -1)
+                       goto decided;
+       }
 
-        /* If file still fits the request, ask ost for updated info.
-           The regular stat is almost of the same speed as some new
-           'glimpse-size-ioctl'. */
+       flags = param->fp_lmd->lmd_flags;
+       if (param->fp_check_size &&
+           ((S_ISREG(stx->stx_mode) && stripe_count) ||
+             S_ISDIR(stx->stx_mode)) &&
+           !(flags & OBD_MD_FLSIZE ||
+             (param->fp_lazy && flags & OBD_MD_FLLAZYSIZE)))
+               decision = 0;
 
-       if ((param->fp_check_size || param->fp_check_blocks) &&
-           ((S_ISREG(st->st_mode) && stripe_count) || S_ISDIR(st->st_mode)))
+       if (param->fp_check_blocks &&
+           ((S_ISREG(stx->stx_mode) && stripe_count) ||
+             S_ISDIR(stx->stx_mode)) &&
+           !(flags & OBD_MD_FLBLOCKS ||
+             (param->fp_lazy && flags & OBD_MD_FLLAZYBLOCKS)))
                decision = 0;
 
+       /* If file still fits the request, ask ost for updated info.
+        * The regular stat is almost of the same speed as some new
+        * 'glimpse-size-ioctl'.
+        */
        if (!decision) {
+               lstat_t st;
+
                 /* For regular files with the stripe the decision may have not
                  * been taken yet if *time or size is to be checked. */
                if (param->fp_obd_index != OBD_NOT_FOUND)
@@ -4740,36 +4859,37 @@ obd_matches:
                         print_failed_tgt(param, path, LL_STATFS_LMV);
 
                if (dir != NULL)
-                       ret = fstat_f(dirfd(dir), st);
+                       ret = fstat_f(dirfd(dir), &st);
                else if (de != NULL)
-                       ret = fstatat_f(dirfd(parent), de->d_name, st,
+                       ret = fstatat_f(dirfd(parent), de->d_name, &st,
                                        AT_SYMLINK_NOFOLLOW);
                else
-                       ret = lstat_f(path, st);
-
-                if (ret) {
-                        if (errno == ENOENT) {
-                                llapi_error(LLAPI_MSG_ERROR, -ENOENT,
-                                            "warning: %s: %s does not exist",
-                                            __func__, path);
-                                goto decided;
-                        } else {
+                       ret = lstat_f(path, &st);
+
+               if (ret) {
+                       if (errno == ENOENT) {
+                               llapi_error(LLAPI_MSG_ERROR, -ENOENT,
+                                           "warning: %s: %s does not exist",
+                                           __func__, path);
+                               goto decided;
+                       } else {
                                ret = -errno;
                                llapi_error(LLAPI_MSG_ERROR, ret,
-                                           "%s: IOC_LOV_GETINFO on %s failed",
+                                           "%s: stat on %s failed",
                                            __func__, path);
                                goto out;
                        }
                }
 
+               convert_lmd_statx(param->fp_lmd, &st, true);
                /* Check the time on osc. */
-               decision = find_time_check(st, param, 0);
+               decision = find_time_check(stx, param, 0);
                if (decision == -1)
                        goto decided;
        }
 
        if (param->fp_check_size) {
-               decision = find_value_cmp(st->st_size, param->fp_size,
+               decision = find_value_cmp(stx->stx_size, param->fp_size,
                                          param->fp_size_sign,
                                          param->fp_exclude_size,
                                          param->fp_size_units, 0);
@@ -4778,7 +4898,8 @@ obd_matches:
        }
 
        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);
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;
-       lstat_t                                  stat;
+       lstatx_t                                 statx;
 };
 
 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,
-                        lstat_t *st)
+                        lstatx_t *stx)
 {
        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;
 
-       lmd_size = sizeof(lmd->lmd_st) +
+       lmd_size = offsetof(typeof(*lmd), lmd_lmm) +
                lov_user_md_size(LOV_MAX_STRIPE_COUNT, LOV_USER_MAGIC_V3);
 
-       if (lmd_size < sizeof(lmd->lmd_st) + XATTR_SIZE_MAX)
-               lmd_size = sizeof(lmd->lmd_st) + XATTR_SIZE_MAX;
+       if (lmd_size < offsetof(typeof(*lmd), lmd_lmm) + XATTR_SIZE_MAX)
+               lmd_size = offsetof(typeof(*lmd), lmd_lmm) + XATTR_SIZE_MAX;
 
        lmd = malloc(lmd_size);
        if (lmd == NULL)
@@ -1024,7 +1024,7 @@ static int ct_md_getattr(const struct hsm_copytool_private *ct,
        if (rc)
                goto out;
 
-       *st = lmd->lmd_st;
+       *stx = lmd->lmd_stx;
 out:
        free(lmd);
 
@@ -1060,7 +1060,7 @@ static int create_restore_volatile(struct hsm_copyaction_private *hcp,
        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;
 
@@ -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) {
-               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;
 
@@ -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 = {
-                       .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);
index d88deb3..e47b303 100644 (file)
@@ -3313,3 +3313,119 @@ int llapi_layout_dom_size(struct llapi_layout *layout, uint64_t *size)
        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,
 };
 
-int get_lmd_info_fd(char *path, int parentfd, int dirfd,
+int get_lmd_info_fd(const char *path, int parentfd, int dirfd,
                    void *lmd_buf, int lmd_len, enum get_lmd_info_type type);
+
+int lov_comp_md_size(struct lov_comp_md_v1 *lcm);
 #endif /* _LUSTREAPI_INTERNAL_H_ */