Whamcloud - gitweb
LU-11971 utils: Send file creation time to clients 07/36507/20
authorQian Yingjin <qian@ddn.com>
Sat, 19 Oct 2019 08:46:36 +0000 (16:46 +0800)
committerOleg Drokin <green@whamcloud.com>
Thu, 14 May 2020 05:39:57 +0000 (05:39 +0000)
Both ext4 and ZFS allow storing the file creation time in the
on-disk inode, and the new statx() API allows returning it to
userspace, but as yet we do not have any mechanism to send it
from the servers to the client.

Add fields into struct mdt_body and an OBD_MD_FLBTIME flag to
allow it to be requested and returned directly from MDTs. It
does not need to get it from the OSTs or in the LVB since those
objects are precreated and their creation time (birth time) is
not accurate.

This patch also adds support to lfs find to query on this field.

Signed-off-by: Qian Yingjin <qian@ddn.com>
Change-Id: Ib122b336695cde511fa6d8fb9eca95a4da701430
Reviewed-on: https://review.whamcloud.com/36507
Tested-by: jenkins <devops@whamcloud.com>
Tested-by: Maloo <maloo@whamcloud.com>
Reviewed-by: Andreas Dilger <adilger@whamcloud.com>
Reviewed-by: Li Xi <lixi@ddn.com>
Reviewed-by: James Simmons <jsimmons@infradead.org>
Reviewed-by: Oleg Drokin <green@whamcloud.com>
18 files changed:
lustre/doc/lfs-find.1
lustre/include/lu_object.h
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/osd-ldiskfs/osd_handler.c
lustre/osd-zfs/osd_internal.h
lustre/osd-zfs/osd_object.c
lustre/osd-zfs/osd_xattr.c
lustre/ptlrpc/pack_generic.c
lustre/ptlrpc/wiretest.c
lustre/tests/sanity.sh
lustre/utils/lfs.c
lustre/utils/liblustreapi.c
lustre/utils/liblustreapi_layout.c
lustre/utils/wiretest.c

index 9181355..ab4271b 100644 (file)
@@ -5,6 +5,7 @@ lfs-find \- Lustre client utility to list files with specific attributes
 .B lfs find \fR<\fIdirectory\fR|\fIfilename \fR...>
       [[\fB!\fR] \fB--atime\fR|\fB-A\fR [\fB-+\fR]\fIn[smhdwy]\fR]
 [[\fB!\fR] \fB--blocks\fR|\fB-b\fR [\fB+-\fR]\fIn\fR]
 .B lfs find \fR<\fIdirectory\fR|\fIfilename \fR...>
       [[\fB!\fR] \fB--atime\fR|\fB-A\fR [\fB-+\fR]\fIn[smhdwy]\fR]
 [[\fB!\fR] \fB--blocks\fR|\fB-b\fR [\fB+-\fR]\fIn\fR]
+      [[\fB!\fR] \fB--btime\fR|\fB--Btime\fR|\fB-B\fR [\fB+-\fR]\fIn[smhdwy]\fR]
       [[\fB!\fR] \fB--ctime\fR|\fB-C\fR [\fB+-\fR]\fIn[smhdwy]\fR]
       [[\fB!\fR] \fB--component-count|\fB--comp-count\fR [\fB+-\fR]\fIn\fR]
       [[\fB!\fR] \fB--component-end|\fB--comp-end\fR|\fB-E\fR [\fB+-\fR]\fIn\fR[\fBKMGTPE\fR]]
       [[\fB!\fR] \fB--ctime\fR|\fB-C\fR [\fB+-\fR]\fIn[smhdwy]\fR]
       [[\fB!\fR] \fB--component-count|\fB--comp-count\fR [\fB+-\fR]\fIn\fR]
       [[\fB!\fR] \fB--component-end|\fB--comp-end\fR|\fB-E\fR [\fB+-\fR]\fIn\fR[\fBKMGTPE\fR]]
@@ -67,6 +68,11 @@ Blocks allocated by the file is \fIn\fR Kibibytes (if no units are given),
 \fIn\fR 512-byte \fBb\fRlocks, or \fBK\fRibi-, \fBM\fRebi-, \fBG\fRibi-,
 \fBT\fRebi-, \fBP\fRebi-, or \fBE\fRbi-bytes if that suffix is given.
 .TP
 \fIn\fR 512-byte \fBb\fRlocks, or \fBK\fRibi-, \fBM\fRebi-, \fBG\fRibi-,
 \fBT\fRebi-, \fBP\fRebi-, or \fBE\fRbi-bytes if that suffix is given.
 .TP
+.BR --btime | --Btime | -B
+File was created \fIn\fR*24 hours ago, see
+--atime
+for full details and options.
+.TP
 .BR --ctime | -C
 File's status was last changed \fIn\fR*24 hours ago, see
 --atime
 .BR --ctime | -C
 File's status was last changed \fIn\fR*24 hours ago, see
 --atime
@@ -209,6 +215,7 @@ ll
 ll
 llw(2i).
 a       The access time of the file \fIreference\fR
 ll
 llw(2i).
 a       The access time of the file \fIreference\fR
+b|B     The birth time of the file \fIreference\fR
 c       The inode status change time of \fIreference\fR
 m       The modification time of the file \fIreference\fR
 t       \fIreference\fR is interpreted directly as a time
 c       The inode status change time of \fIreference\fR
 m       The modification time of the file \fIreference\fR
 t       \fIreference\fR is interpreted directly as a time
@@ -231,7 +238,10 @@ with unspecified times at the start of that minute or day, unspecified dates
 being "today", and "@%s" or "%s" the seconds since the Unix epoch (see
 .BR strftime (3)
 for details of the time formats).  Otherwise, it will report an error.
 being "today", and "@%s" or "%s" the seconds since the Unix epoch (see
 .BR strftime (3)
 for details of the time formats).  Otherwise, it will report an error.
-
+If you try to use the birth time of a reference file, and the birth
+time cannot be determined, a fatal error message results.  If you
+specify a test which refers to the birth time of files being examined,
+this test will fail for any files where the birth time is unknown.
 .TP
 .BR --ost | -O
 File has an object on the specified OST(s).  The OST names can be specified
 .TP
 .BR --ost | -O
 File has an object on the specified OST(s).  The OST names can be specified
index e656d94..a9fa482 100644 (file)
@@ -397,35 +397,37 @@ struct lu_attr {
         *
         * \see enum la_valid
         */
         *
         * \see enum la_valid
         */
-       __u64          la_valid;
+       __u64           la_valid;
         /** size in bytes */
         /** size in bytes */
-        __u64          la_size;
+       __u64           la_size;
        /** modification time in seconds since Epoch */
        s64             la_mtime;
        /** access time in seconds since Epoch */
        s64             la_atime;
        /** change time in seconds since Epoch */
        s64             la_ctime;
        /** modification time in seconds since Epoch */
        s64             la_mtime;
        /** access time in seconds since Epoch */
        s64             la_atime;
        /** change time in seconds since Epoch */
        s64             la_ctime;
+       /** create time in seconds since Epoch */
+       s64             la_btime;
         /** 512-byte blocks allocated to object */
         /** 512-byte blocks allocated to object */
-        __u64          la_blocks;
+       __u64           la_blocks;
         /** permission bits and file type */
         /** permission bits and file type */
-        __u32          la_mode;
+       __u32           la_mode;
         /** owner id */
         /** owner id */
-        __u32          la_uid;
+       __u32           la_uid;
         /** group id */
         /** group id */
-        __u32          la_gid;
+       __u32           la_gid;
         /** object flags */
         /** object flags */
-        __u32          la_flags;
+       __u32           la_flags;
         /** number of persistent references to this object */
         /** number of persistent references to this object */
-        __u32          la_nlink;
+       __u32           la_nlink;
         /** blk bits of the object*/
         /** blk bits of the object*/
-        __u32          la_blkbits;
+       __u32           la_blkbits;
         /** blk size of the object*/
         /** blk size of the object*/
-        __u32          la_blksize;
+       __u32           la_blksize;
         /** real device */
         /** real device */
-        __u32          la_rdev;
+       __u32           la_rdev;
        /** project id */
        /** project id */
-       __u32          la_projid;
+       __u32           la_projid;
        /** set layout version to OST objects. */
        __u32           la_layout_version;
 };
        /** set layout version to OST objects. */
        __u32           la_layout_version;
 };
index a9ecd8d..009a622 100644 (file)
@@ -196,6 +196,7 @@ enum {
        NEWERXY_ATIME = 0,      /* neweraY */
        NEWERXY_MTIME = 1,      /* newermY */
        NEWERXY_CTIME = 2,      /* newercY */
        NEWERXY_ATIME = 0,      /* neweraY */
        NEWERXY_MTIME = 1,      /* newermY */
        NEWERXY_CTIME = 2,      /* newercY */
+       NEWERXY_BTIME = 3,      /* newerbY | newerBY */
        NEWERXY_MAX,
 };
 
        NEWERXY_MAX,
 };
 
@@ -208,7 +209,7 @@ struct find_param {
        time_t                   fp_atime;
        time_t                   fp_mtime;
        time_t                   fp_ctime;
        time_t                   fp_atime;
        time_t                   fp_mtime;
        time_t                   fp_ctime;
-       /* {a,m,c}sign cannot be bitfields due to using pointers to
+       /* {a,m,c,b}sign cannot be bitfields due to using pointers to
         * access them during argument parsing. */
        int                      fp_asign;
        int                      fp_msign;
         * access them during argument parsing. */
        int                      fp_asign;
        int                      fp_msign;
@@ -291,12 +292,13 @@ struct find_param {
                                 fp_exclude_ext_size:1,
                                 fp_lazy:1,
                                 fp_newerxy:1,
                                 fp_exclude_ext_size:1,
                                 fp_lazy:1,
                                 fp_newerxy:1,
-                                fp_unused_bit2:1, /* All of these unused bit */
-                                fp_unused_bit3:1, /* fields available to use.*/
-                                fp_unused_bit4:1, /* Once all unused fields  */
-                                fp_unused_bit5:1, /* are used we need to add */
-                                fp_unused_bit6:1, /* a separate flag field at*/
-                                fp_unused_bit7:1; /* the end of the struct.  */
+                                fp_exclude_btime:1,
+                                fp_unused_bit3:1, /* All of these unused bit */
+                                fp_unused_bit4:1, /* fields available to use.*/
+                                fp_unused_bit5:1, /* Once all unused fields  */
+                                fp_unused_bit6:1, /* are used we need to add */
+                                fp_unused_bit7:1; /* a separate flag field at*/
+                                                  /* the end of the struct.  */
 
        enum llapi_layout_verbose fp_verbose;
        int                      fp_quiet;
 
        enum llapi_layout_verbose fp_verbose;
        int                      fp_quiet;
@@ -362,6 +364,9 @@ struct find_param {
         * fp_newery[NEWERXY_MAX][1]: ! -- newerXY reference
         */
        time_t                   fp_newery[NEWERXY_MAX][2];
         * fp_newery[NEWERXY_MAX][1]: ! -- newerXY reference
         */
        time_t                   fp_newery[NEWERXY_MAX][2];
+
+       time_t                   fp_btime;
+       int                      fp_bsign;
 };
 
 int llapi_ostlist(char *path, struct find_param *param);
 };
 
 int llapi_ostlist(char *path, struct find_param *param);
index 57d2afe..9b5eb9f 100644 (file)
@@ -1300,6 +1300,8 @@ lov_mds_md_max_stripe_count(__kernel_size_t buf_size, __u32 lmm_magic)
 #define OBD_MD_FLLAZYSIZE    (0x0400000000000000ULL) /* Lazy size */
 #define OBD_MD_FLLAZYBLOCKS  (0x0800000000000000ULL) /* Lazy blocks */
 
 #define OBD_MD_FLLAZYSIZE    (0x0400000000000000ULL) /* Lazy size */
 #define OBD_MD_FLLAZYBLOCKS  (0x0800000000000000ULL) /* Lazy blocks */
 
+#define OBD_MD_FLBTIME       (0x1000000000000000ULL) /* birth time */
+
 #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)
@@ -1309,7 +1311,7 @@ lov_mds_md_max_stripe_count(__kernel_size_t buf_size, __u32 lmm_magic)
                          OBD_MD_FLMODE  | OBD_MD_FLTYPE  | OBD_MD_FLUID   | \
                          OBD_MD_FLGID   | OBD_MD_FLFLAGS | OBD_MD_FLNLINK | \
                          OBD_MD_FLPARENT | OBD_MD_FLRDEV  | OBD_MD_FLGROUP | \
                          OBD_MD_FLMODE  | OBD_MD_FLTYPE  | OBD_MD_FLUID   | \
                          OBD_MD_FLGID   | OBD_MD_FLFLAGS | OBD_MD_FLNLINK | \
                          OBD_MD_FLPARENT | OBD_MD_FLRDEV  | OBD_MD_FLGROUP | \
-                         OBD_MD_FLPROJID)
+                         OBD_MD_FLPROJID | OBD_MD_FLBTIME)
 
 #define OBD_MD_FLXATTRALL (OBD_MD_FLXATTR | OBD_MD_FLXATTRLS)
 
 
 #define OBD_MD_FLXATTRALL (OBD_MD_FLXATTR | OBD_MD_FLXATTRLS)
 
@@ -1814,8 +1816,8 @@ struct mdt_body {
        __u32   mbo_projid;
        __u64   mbo_dom_size; /* size of DOM component */
        __u64   mbo_dom_blocks; /* blocks consumed by DOM component */
        __u32   mbo_projid;
        __u64   mbo_dom_size; /* size of DOM component */
        __u64   mbo_dom_blocks; /* blocks consumed by DOM component */
-       __u64   mbo_padding_8; /* also fix lustre_swab_mdt_body */
-       __u64   mbo_padding_9;
+       __u64   mbo_btime;
+       __u64   mbo_padding_9; /* also fix lustre_swab_mdt_body */
        __u64   mbo_padding_10;
 }; /* 216 */
 
        __u64   mbo_padding_10;
 }; /* 216 */
 
index 93fc33a..65e41f1 100644 (file)
@@ -1389,6 +1389,7 @@ enum la_valid {
        LA_LAYOUT_VERSION = 1 << 16,    /* 0x10000 */
        LA_LSIZE        = 1 << 17,      /* 0x20000 */
        LA_LBLOCKS      = 1 << 18,      /* 0x40000 */
        LA_LAYOUT_VERSION = 1 << 16,    /* 0x10000 */
        LA_LSIZE        = 1 << 17,      /* 0x20000 */
        LA_LBLOCKS      = 1 << 18,      /* 0x40000 */
+       LA_BTIME        = 1 << 19,      /* 0x80000 */
        /**
         * Attributes must be transmitted to OST objects
         */
        /**
         * Attributes must be transmitted to OST objects
         */
index cf6e43c..da83791 100644 (file)
@@ -1804,11 +1804,12 @@ out_rmdir:
                        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_atime.tv_sec = body->mbo_atime;
                        stx.stx_ctime.tv_sec = body->mbo_ctime;
                        stx.stx_mtime.tv_sec = body->mbo_mtime;
+                       stx.stx_btime.tv_sec = body->mbo_btime;
                        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_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;
+                       stx.stx_mask |= STATX_BASIC_STATS | STATX_BTIME;
 
                        /*
                         * For a striped directory, the size and blocks returned
 
                        /*
                         * For a striped directory, the size and blocks returned
index aa843fe..0f3ff88 100644 (file)
@@ -727,6 +727,10 @@ void mdt_pack_attr2body(struct mdt_thread_info *info, struct mdt_body *b,
                b->mbo_ctime = attr->la_ctime;
                b->mbo_valid |= OBD_MD_FLCTIME;
        }
                b->mbo_ctime = attr->la_ctime;
                b->mbo_valid |= OBD_MD_FLCTIME;
        }
+       if (attr->la_valid & LA_BTIME) {
+               b->mbo_btime = attr->la_btime;
+               b->mbo_valid |= OBD_MD_FLBTIME;
+       }
        if (attr->la_valid & LA_FLAGS) {
                b->mbo_flags = attr->la_flags;
                b->mbo_valid |= OBD_MD_FLFLAGS;
        if (attr->la_valid & LA_FLAGS) {
                b->mbo_flags = attr->la_flags;
                b->mbo_valid |= OBD_MD_FLFLAGS;
index e3006f6..8337dd2 100644 (file)
@@ -2594,11 +2594,12 @@ static void osd_inode_getattr(const struct lu_env *env,
        attr->la_valid  |= LA_ATIME | LA_MTIME | LA_CTIME | LA_MODE |
                           LA_SIZE | LA_BLOCKS | LA_UID | LA_GID |
                           LA_PROJID | LA_FLAGS | LA_NLINK | LA_RDEV |
        attr->la_valid  |= LA_ATIME | LA_MTIME | LA_CTIME | LA_MODE |
                           LA_SIZE | LA_BLOCKS | LA_UID | LA_GID |
                           LA_PROJID | LA_FLAGS | LA_NLINK | LA_RDEV |
-                          LA_BLKSIZE | LA_TYPE;
+                          LA_BLKSIZE | LA_TYPE | LA_BTIME;
 
        attr->la_atime = inode->i_atime.tv_sec;
        attr->la_mtime = inode->i_mtime.tv_sec;
        attr->la_ctime = inode->i_ctime.tv_sec;
 
        attr->la_atime = inode->i_atime.tv_sec;
        attr->la_mtime = inode->i_mtime.tv_sec;
        attr->la_ctime = inode->i_ctime.tv_sec;
+       attr->la_btime = LDISKFS_I(inode)->i_crtime.tv_sec;
        attr->la_mode    = inode->i_mode;
        attr->la_size    = i_size_read(inode);
        attr->la_blocks  = inode->i_blocks;
        attr->la_mode    = inode->i_mode;
        attr->la_size    = i_size_read(inode);
        attr->la_blocks  = inode->i_blocks;
index 443a1ed..737ec68 100644 (file)
@@ -181,6 +181,7 @@ struct osa_attr {
        uint64_t        atime[2];
        uint64_t        mtime[2];
        uint64_t        ctime[2];
        uint64_t        atime[2];
        uint64_t        mtime[2];
        uint64_t        ctime[2];
+       uint64_t        btime[2];
 };
 
 
 };
 
 
index cc8f1da..f28bcb7 100644 (file)
@@ -194,12 +194,14 @@ static int __osd_object_attr_get(const struct lu_env *env, struct osd_device *o,
 
        LASSERT(obj->oo_dn != NULL);
 
 
        LASSERT(obj->oo_dn != NULL);
 
-       la->la_valid |= LA_ATIME | LA_MTIME | LA_CTIME | LA_MODE | LA_TYPE |
-                       LA_SIZE | LA_UID | LA_GID | LA_FLAGS | LA_NLINK;
+       la->la_valid |= LA_ATIME | LA_MTIME | LA_CTIME | LA_BTIME | LA_MODE |
+                       LA_TYPE | LA_SIZE | LA_UID | LA_GID | LA_FLAGS |
+                       LA_NLINK;
 
        SA_ADD_BULK_ATTR(bulk, cnt, SA_ZPL_ATIME(o), NULL, osa->atime, 16);
        SA_ADD_BULK_ATTR(bulk, cnt, SA_ZPL_MTIME(o), NULL, osa->mtime, 16);
        SA_ADD_BULK_ATTR(bulk, cnt, SA_ZPL_CTIME(o), NULL, osa->ctime, 16);
 
        SA_ADD_BULK_ATTR(bulk, cnt, SA_ZPL_ATIME(o), NULL, osa->atime, 16);
        SA_ADD_BULK_ATTR(bulk, cnt, SA_ZPL_MTIME(o), NULL, osa->mtime, 16);
        SA_ADD_BULK_ATTR(bulk, cnt, SA_ZPL_CTIME(o), NULL, osa->ctime, 16);
+       SA_ADD_BULK_ATTR(bulk, cnt, SA_ZPL_CRTIME(o), NULL, osa->btime, 16);
        SA_ADD_BULK_ATTR(bulk, cnt, SA_ZPL_MODE(o), NULL, &osa->mode, 8);
        SA_ADD_BULK_ATTR(bulk, cnt, SA_ZPL_SIZE(o), NULL, &osa->size, 8);
        SA_ADD_BULK_ATTR(bulk, cnt, SA_ZPL_LINKS(o), NULL, &osa->nlink, 8);
        SA_ADD_BULK_ATTR(bulk, cnt, SA_ZPL_MODE(o), NULL, &osa->mode, 8);
        SA_ADD_BULK_ATTR(bulk, cnt, SA_ZPL_SIZE(o), NULL, &osa->size, 8);
        SA_ADD_BULK_ATTR(bulk, cnt, SA_ZPL_LINKS(o), NULL, &osa->nlink, 8);
@@ -234,6 +236,7 @@ static int __osd_object_attr_get(const struct lu_env *env, struct osd_device *o,
        la->la_atime = osa->atime[0];
        la->la_mtime = osa->mtime[0];
        la->la_ctime = osa->ctime[0];
        la->la_atime = osa->atime[0];
        la->la_mtime = osa->mtime[0];
        la->la_ctime = osa->ctime[0];
+       la->la_btime = osa->btime[0];
        la->la_mode = osa->mode;
        la->la_uid = osa->uid;
        la->la_gid = osa->gid;
        la->la_mode = osa->mode;
        la->la_uid = osa->uid;
        la->la_gid = osa->gid;
@@ -1525,7 +1528,6 @@ int __osd_attr_init(const struct lu_env *env, struct osd_device *osd,
        sa_bulk_attr_t *bulk = osd_oti_get(env)->oti_attr_bulk;
        struct osa_attr *osa = &osd_oti_get(env)->oti_osa;
        uint64_t gen;
        sa_bulk_attr_t *bulk = osd_oti_get(env)->oti_attr_bulk;
        struct osa_attr *osa = &osd_oti_get(env)->oti_osa;
        uint64_t gen;
-       uint64_t crtime[2];
        inode_timespec_t now;
        int cnt;
        int rc;
        inode_timespec_t now;
        int cnt;
        int rc;
@@ -1537,7 +1539,7 @@ int __osd_attr_init(const struct lu_env *env, struct osd_device *osd,
 
        gen = dmu_tx_get_txg(tx);
        gethrestime(&now);
 
        gen = dmu_tx_get_txg(tx);
        gethrestime(&now);
-       ZFS_TIME_ENCODE(&now, crtime);
+       ZFS_TIME_ENCODE(&now, osa->btime);
 
        osa->atime[0] = la->la_atime;
        osa->ctime[0] = la->la_ctime;
 
        osa->atime[0] = la->la_atime;
        osa->ctime[0] = la->la_ctime;
@@ -1587,7 +1589,7 @@ int __osd_attr_init(const struct lu_env *env, struct osd_device *osd,
        SA_ADD_BULK_ATTR(bulk, cnt, SA_ZPL_ATIME(osd), NULL, osa->atime, 16);
        SA_ADD_BULK_ATTR(bulk, cnt, SA_ZPL_MTIME(osd), NULL, osa->mtime, 16);
        SA_ADD_BULK_ATTR(bulk, cnt, SA_ZPL_CTIME(osd), NULL, osa->ctime, 16);
        SA_ADD_BULK_ATTR(bulk, cnt, SA_ZPL_ATIME(osd), NULL, osa->atime, 16);
        SA_ADD_BULK_ATTR(bulk, cnt, SA_ZPL_MTIME(osd), NULL, osa->mtime, 16);
        SA_ADD_BULK_ATTR(bulk, cnt, SA_ZPL_CTIME(osd), NULL, osa->ctime, 16);
-       SA_ADD_BULK_ATTR(bulk, cnt, SA_ZPL_CRTIME(osd), NULL, crtime, 16);
+       SA_ADD_BULK_ATTR(bulk, cnt, SA_ZPL_CRTIME(osd), NULL, osa->btime, 16);
        SA_ADD_BULK_ATTR(bulk, cnt, SA_ZPL_LINKS(osd), NULL, &osa->nlink, 8);
 #ifdef ZFS_PROJINHERIT
        if (osd->od_projectused_dn)
        SA_ADD_BULK_ATTR(bulk, cnt, SA_ZPL_LINKS(osd), NULL, &osa->nlink, 8);
 #ifdef ZFS_PROJINHERIT
        if (osd->od_projectused_dn)
index 0db69f3..91ed638 100644 (file)
@@ -430,7 +430,7 @@ int __osd_sa_attr_init(const struct lu_env *env, struct osd_object *obj,
        struct osa_attr *osa = &osd_oti_get(env)->oti_osa;
        struct lu_buf *lb = &osd_oti_get(env)->oti_xattr_lbuf;
        struct osd_device *osd = osd_obj2dev(obj);
        struct osa_attr *osa = &osd_oti_get(env)->oti_osa;
        struct lu_buf *lb = &osd_oti_get(env)->oti_xattr_lbuf;
        struct osd_device *osd = osd_obj2dev(obj);
-       uint64_t crtime[2], gen;
+       uint64_t gen;
        inode_timespec_t now;
        size_t size;
        int rc, cnt;
        inode_timespec_t now;
        size_t size;
        int rc, cnt;
@@ -440,8 +440,10 @@ int __osd_sa_attr_init(const struct lu_env *env, struct osd_object *obj,
 
        gen = dmu_tx_get_txg(oh->ot_tx);
        gethrestime(&now);
 
        gen = dmu_tx_get_txg(oh->ot_tx);
        gethrestime(&now);
-       ZFS_TIME_ENCODE(&now, crtime);
+       ZFS_TIME_ENCODE(&now, osa->btime);
 
 
+       obj->oo_attr.la_valid |= LA_BTIME;
+       obj->oo_attr.la_btime = osa->btime[0];
        osa->atime[0] = obj->oo_attr.la_atime;
        osa->ctime[0] = obj->oo_attr.la_ctime;
        osa->mtime[0] = obj->oo_attr.la_mtime;
        osa->atime[0] = obj->oo_attr.la_atime;
        osa->ctime[0] = obj->oo_attr.la_ctime;
        osa->mtime[0] = obj->oo_attr.la_mtime;
@@ -475,7 +477,7 @@ int __osd_sa_attr_init(const struct lu_env *env, struct osd_object *obj,
        SA_ADD_BULK_ATTR(bulk, cnt, SA_ZPL_ATIME(osd), NULL, osa->atime, 16);
        SA_ADD_BULK_ATTR(bulk, cnt, SA_ZPL_MTIME(osd), NULL, osa->mtime, 16);
        SA_ADD_BULK_ATTR(bulk, cnt, SA_ZPL_CTIME(osd), NULL, osa->ctime, 16);
        SA_ADD_BULK_ATTR(bulk, cnt, SA_ZPL_ATIME(osd), NULL, osa->atime, 16);
        SA_ADD_BULK_ATTR(bulk, cnt, SA_ZPL_MTIME(osd), NULL, osa->mtime, 16);
        SA_ADD_BULK_ATTR(bulk, cnt, SA_ZPL_CTIME(osd), NULL, osa->ctime, 16);
-       SA_ADD_BULK_ATTR(bulk, cnt, SA_ZPL_CRTIME(osd), NULL, crtime, 16);
+       SA_ADD_BULK_ATTR(bulk, cnt, SA_ZPL_CRTIME(osd), NULL, osa->btime, 16);
        SA_ADD_BULK_ATTR(bulk, cnt, SA_ZPL_LINKS(osd), NULL, &osa->nlink, 8);
 #ifdef ZFS_PROJINHERIT
        if (osd->od_projectused_dn)
        SA_ADD_BULK_ATTR(bulk, cnt, SA_ZPL_LINKS(osd), NULL, &osa->nlink, 8);
 #ifdef ZFS_PROJINHERIT
        if (osd->od_projectused_dn)
index 8cc0ff6..973e3f0 100644 (file)
@@ -1987,7 +1987,7 @@ void lustre_swab_mdt_body(struct mdt_body *b)
        __swab32s(&b->mbo_projid);
        __swab64s(&b->mbo_dom_size);
        __swab64s(&b->mbo_dom_blocks);
        __swab32s(&b->mbo_projid);
        __swab64s(&b->mbo_dom_size);
        __swab64s(&b->mbo_dom_blocks);
-       BUILD_BUG_ON(offsetof(typeof(*b), mbo_padding_8) == 0);
+       __swab64s(&b->mbo_btime);
        BUILD_BUG_ON(offsetof(typeof(*b), mbo_padding_9) == 0);
        BUILD_BUG_ON(offsetof(typeof(*b), mbo_padding_10) == 0);
 }
        BUILD_BUG_ON(offsetof(typeof(*b), mbo_padding_9) == 0);
        BUILD_BUG_ON(offsetof(typeof(*b), mbo_padding_10) == 0);
 }
index 3b5431b..e069b60 100644 (file)
@@ -2493,10 +2493,10 @@ void lustre_assert_wire_constants(void)
                 (long long)(int)offsetof(struct mdt_body, mbo_dom_blocks));
        LASSERTF((int)sizeof(((struct mdt_body *)0)->mbo_dom_blocks) == 8, "found %lld\n",
                 (long long)(int)sizeof(((struct mdt_body *)0)->mbo_dom_blocks));
                 (long long)(int)offsetof(struct mdt_body, mbo_dom_blocks));
        LASSERTF((int)sizeof(((struct mdt_body *)0)->mbo_dom_blocks) == 8, "found %lld\n",
                 (long long)(int)sizeof(((struct mdt_body *)0)->mbo_dom_blocks));
-       LASSERTF((int)offsetof(struct mdt_body, mbo_padding_8) == 192, "found %lld\n",
-                (long long)(int)offsetof(struct mdt_body, mbo_padding_8));
-       LASSERTF((int)sizeof(((struct mdt_body *)0)->mbo_padding_8) == 8, "found %lld\n",
-                (long long)(int)sizeof(((struct mdt_body *)0)->mbo_padding_8));
+       LASSERTF((int)offsetof(struct mdt_body, mbo_btime) == 192, "found %lld\n",
+                (long long)(int)offsetof(struct mdt_body, mbo_btime));
+       LASSERTF((int)sizeof(((struct mdt_body *)0)->mbo_btime) == 8, "found %lld\n",
+                (long long)(int)sizeof(((struct mdt_body *)0)->mbo_btime));
        LASSERTF((int)offsetof(struct mdt_body, mbo_padding_9) == 200, "found %lld\n",
                 (long long)(int)offsetof(struct mdt_body, mbo_padding_9));
        LASSERTF((int)sizeof(((struct mdt_body *)0)->mbo_padding_9) == 8, "found %lld\n",
        LASSERTF((int)offsetof(struct mdt_body, mbo_padding_9) == 200, "found %lld\n",
                 (long long)(int)offsetof(struct mdt_body, mbo_padding_9));
        LASSERTF((int)sizeof(((struct mdt_body *)0)->mbo_padding_9) == 8, "found %lld\n",
index fb540aa..1b32ad1 100755 (executable)
@@ -5880,18 +5880,26 @@ test_newerXY_base() {
        local negref
 
        if [ $y == "t" ]; then
        local negref
 
        if [ $y == "t" ]; then
-               ref="\"$(date +"%Y-%m-%d %H:%M:%S")\""
+               if [ $x == "b" ]; then
+                       ref="\"$(do_facet mds1 date +"%Y-%m-%d\ %H:%M:%S")\""
+               else
+                       ref="\"$(date +"%Y-%m-%d %H:%M:%S")\""
+               fi
        else
        else
-               ref=$DIR/$tfile.newer
+               ref=$DIR/$tfile.newer.$x$y
                touch $ref || error "touch $ref failed"
        fi
        sleep 2
        setup_56 $dir $NUMFILES $NUMDIRS "-i0 -c1" "-i0 -c1"
        sleep 2
        if [ $y == "t" ]; then
                touch $ref || error "touch $ref failed"
        fi
        sleep 2
        setup_56 $dir $NUMFILES $NUMDIRS "-i0 -c1" "-i0 -c1"
        sleep 2
        if [ $y == "t" ]; then
-               negref="\"$(date +"%Y-%m-%d %H:%M:%S")\""
+               if [ $x == "b" ]; then
+                       negref="\"$(do_facet mds1 date +"%Y-%m-%d\ %H:%M:%S")\""
+               else
+                       negref="\"$(date +"%Y-%m-%d %H:%M:%S")\""
+               fi
        else
        else
-               negref=$DIR/$tfile.newerneg
+               negref=$DIR/$tfile.negnewer.$x$y
                touch $negref || error "touch $negref failed"
        fi
 
                touch $negref || error "touch $negref failed"
        fi
 
@@ -5916,6 +5924,7 @@ test_newerXY_base() {
 }
 
 test_56oc() {
 }
 
 test_56oc() {
+       test_newerXY_base "b" "t"
        test_newerXY_base "a" "a"
        test_newerXY_base "a" "m"
        test_newerXY_base "a" "c"
        test_newerXY_base "a" "a"
        test_newerXY_base "a" "m"
        test_newerXY_base "a" "c"
@@ -5925,12 +5934,96 @@ test_56oc() {
        test_newerXY_base "c" "a"
        test_newerXY_base "c" "m"
        test_newerXY_base "c" "c"
        test_newerXY_base "c" "a"
        test_newerXY_base "c" "m"
        test_newerXY_base "c" "c"
+       test_newerXY_base "b" "b"
        test_newerXY_base "a" "t"
        test_newerXY_base "m" "t"
        test_newerXY_base "c" "t"
        test_newerXY_base "a" "t"
        test_newerXY_base "m" "t"
        test_newerXY_base "c" "t"
+       test_newerXY_base "b" "t"
 }
 run_test 56oc "check lfs find -newerXY work"
 
 }
 run_test 56oc "check lfs find -newerXY work"
 
+btime_supported() {
+       local dir=$DIR/$tdir
+       local rc
+
+       mkdir -p $dir
+       touch $dir/$tfile
+       $LFS find $dir -btime -1d -type f
+       rc=$?
+       rm -rf $dir
+       return $rc
+}
+
+test_56od() {
+       [ $MDS1_VERSION -lt $(version_code 2.13.53) ] &&
+               ! btime_supported && skip "btime unsupported on MDS"
+
+       [ $CLIENT_VERSION -lt $(version_code 2.13.53) ] &&
+               ! btime_supported && skip "btime unsupported on clients"
+
+       local dir=$DIR/$tdir
+       local ref=$DIR/$tfile.ref
+       local negref=$DIR/$tfile.negref
+
+       mkdir $dir || error "mkdir $dir failed"
+       touch $dir/$tfile.n1 || error "touch $dir/$tfile.n1 failed"
+       touch $dir/$tfile.n2 || error "touch $dir/$tfile.n2 failed"
+       mkdir $dir/$tdir.n1 || error "mkdir $dir/$tdir.n1 failed"
+       mkdir $dir/$tdir.n2 || error "mkdir $dir/$tdir.n2 failed"
+       touch $ref || error "touch $ref failed"
+       # sleep 3 seconds at least
+       sleep 3
+
+       local before=$(do_facet mds1 date +%s)
+       local skew=$(($(date +%s) - before + 1))
+
+       if (( skew < 0 && skew > -5 )); then
+               sleep $((0 - skew + 1))
+               skew=0
+       fi
+
+       # Set the dir stripe params to limit files all on MDT0,
+       # otherwise we need to calc the max clock skew between
+       # the client and MDTs.
+       setup_56 $dir/d.btime $NUMFILES $NUMDIRS "-i0 -c1" "-i0 -c1"
+       sleep 2
+       touch $negref || error "touch $negref failed"
+
+       local cmd="$LFS find $dir -newerbb $ref ! -newerbb $negref -type f"
+       local nums=$($cmd | wc -l)
+       local expected=$(((NUMFILES + 1) * NUMDIRS))
+
+       [ $nums -eq $expected ] ||
+               error "'$cmd' wrong: found $nums, expected $expected"
+
+       cmd="$LFS find $dir -newerbb $ref ! -newerbb $negref -type d"
+       nums=$($cmd | wc -l)
+       expected=$((NUMFILES + 1))
+       [ $nums -eq $expected ] ||
+               error "'$cmd' wrong: found $nums, expected $expected"
+
+       [ $skew -lt 0 ] && return
+
+       local after=$(do_facet mds1 date +%s)
+       local age=$((after - before + 1 + skew))
+
+       cmd="$LFS find $dir -btime -${age}s -type f"
+       nums=$($cmd | wc -l)
+       expected=$(((NUMFILES + 1) * NUMDIRS))
+
+       echo "Clock skew between client and server: $skew, age:$age"
+       [ $nums -eq $expected ] ||
+               error "'$cmd' wrong: found $nums, expected $expected"
+
+       expected=$(($NUMDIRS + 1))
+       cmd="$LFS find $dir -btime -${age}s -type d"
+       nums=$($cmd | wc -l)
+       [ $nums -eq $expected ] ||
+               error "'$cmd' wrong: found $nums, expected $expected"
+       rm -f $ref $negref || error "Failed to remove $ref $negref"
+}
+run_test 56od "check lfs find -btime with units"
+
 test_56p() {
        [ $RUNAS_ID -eq $UID ] &&
                skip_env "RUNAS_ID = UID = $UID -- skipping"
 test_56p() {
        [ $RUNAS_ID -eq $UID ] &&
                skip_env "RUNAS_ID = UID = $UID -- skipping"
index 4407f56..1490ffe 100644 (file)
@@ -457,8 +457,9 @@ command_t cmdlist[] = {
         "find files matching given attributes recursively in directory tree.\n"
         "usage: find <directory|filename> ...\n"
         "     [[!] --atime|-A [+-]N[smhdwy]] [[!] --ctime|-C [+-]N[smhdwy]]\n"
         "find files matching given attributes recursively in directory tree.\n"
         "usage: find <directory|filename> ...\n"
         "     [[!] --atime|-A [+-]N[smhdwy]] [[!] --ctime|-C [+-]N[smhdwy]]\n"
-        "     [[!] --mtime|-M [+-]N[smhdwy]] [[!] --blocks|-b N]\n"
-        "     [[!] --newer[XY] <reference>]\n"
+        "     [[!] --mtime|-M [+-]N[smhdwy]]\n"
+        "     [[!] --btime|--Btime|-B [+-]N[smhdwy]]\n"
+        "     [[!] --newer[XY] <reference>] [[!] --blocks|-b N]\n"
         "     [--maxdepth|-D N] [[!] --mdt-index|--mdt|-m <uuid|index,...>]\n"
         "     [[!] --name|-n <pattern>] [[!] --ost|-O <uuid|index,...>]\n"
         "     [--print|-P] [--print0|-0] [[!] --size|-s [+-]N[bkMGTPE]]\n"
         "     [--maxdepth|-D N] [[!] --mdt-index|--mdt|-m <uuid|index,...>]\n"
         "     [[!] --name|-n <pattern>] [[!] --ost|-O <uuid|index,...>]\n"
         "     [--print|-P] [--print0|-0] [[!] --size|-s [+-]N[bkMGTPE]]\n"
@@ -3069,6 +3070,7 @@ static int lfs_setstripe_internal(int argc, char **argv,
 /* find        { .val = 'A',   .name = "atime",        .has_arg = required_argument }*/
        /* --block is only valid in migrate mode */
        { .val = 'b',   .name = "block",        .has_arg = no_argument },
 /* find        { .val = 'A',   .name = "atime",        .has_arg = required_argument }*/
        /* --block is only valid in migrate mode */
        { .val = 'b',   .name = "block",        .has_arg = no_argument },
+/* find        { .val = 'B',   .name = "btime",        .has_arg = required_argument }*/
        { .val = LFS_COMP_ADD_OPT,
                        .name = "comp-add",     .has_arg = no_argument },
        { .val = LFS_COMP_ADD_OPT,
        { .val = LFS_COMP_ADD_OPT,
                        .name = "comp-add",     .has_arg = no_argument },
        { .val = LFS_COMP_ADD_OPT,
@@ -4168,6 +4170,8 @@ static int lfs_find(int argc, char **argv)
         struct option long_opts[] = {
        { .val = 'A',   .name = "atime",        .has_arg = required_argument },
        { .val = 'b',   .name = "blocks",       .has_arg = required_argument },
         struct option long_opts[] = {
        { .val = 'A',   .name = "atime",        .has_arg = required_argument },
        { .val = 'b',   .name = "blocks",       .has_arg = required_argument },
+       { .val = 'B',   .name = "btime",        .has_arg = required_argument },
+       { .val = 'B',   .name = "Btime",        .has_arg = required_argument },
        { .val = LFS_COMP_COUNT_OPT,
                        .name = "comp-count",   .has_arg = required_argument },
        { .val = LFS_COMP_COUNT_OPT,
        { .val = LFS_COMP_COUNT_OPT,
                        .name = "comp-count",   .has_arg = required_argument },
        { .val = LFS_COMP_COUNT_OPT,
@@ -4196,23 +4200,49 @@ static int lfs_find(int argc, char **argv)
        { .val = LFS_NEWERXY_OPT,
                        .name = "newerac",      .has_arg = required_argument},
        { .val = LFS_NEWERXY_OPT,
        { .val = LFS_NEWERXY_OPT,
                        .name = "newerac",      .has_arg = required_argument},
        { .val = LFS_NEWERXY_OPT,
+                       .name = "newerab",      .has_arg = required_argument},
+       { .val = LFS_NEWERXY_OPT,
                        .name = "newerma",      .has_arg = required_argument},
        { .val = LFS_NEWERXY_OPT,
                        .name = "newermm",      .has_arg = required_argument},
        { .val = LFS_NEWERXY_OPT,
                        .name = "newermc",      .has_arg = required_argument},
        { .val = LFS_NEWERXY_OPT,
                        .name = "newerma",      .has_arg = required_argument},
        { .val = LFS_NEWERXY_OPT,
                        .name = "newermm",      .has_arg = required_argument},
        { .val = LFS_NEWERXY_OPT,
                        .name = "newermc",      .has_arg = required_argument},
        { .val = LFS_NEWERXY_OPT,
+                       .name = "newermb",      .has_arg = required_argument},
+       { .val = LFS_NEWERXY_OPT,
                        .name = "newerca",      .has_arg = required_argument},
        { .val = LFS_NEWERXY_OPT,
                        .name = "newercm",      .has_arg = required_argument},
        { .val = LFS_NEWERXY_OPT,
                        .name = "newercc",      .has_arg = required_argument},
        { .val = LFS_NEWERXY_OPT,
                        .name = "newerca",      .has_arg = required_argument},
        { .val = LFS_NEWERXY_OPT,
                        .name = "newercm",      .has_arg = required_argument},
        { .val = LFS_NEWERXY_OPT,
                        .name = "newercc",      .has_arg = required_argument},
        { .val = LFS_NEWERXY_OPT,
+                       .name = "newercb",      .has_arg = required_argument},
+       { .val = LFS_NEWERXY_OPT,
+                       .name = "newerba",      .has_arg = required_argument},
+       { .val = LFS_NEWERXY_OPT,
+                       .name = "newerbm",      .has_arg = required_argument},
+       { .val = LFS_NEWERXY_OPT,
+                       .name = "newerbc",      .has_arg = required_argument},
+       { .val = LFS_NEWERXY_OPT,
+                       .name = "newerbb",      .has_arg = required_argument},
+       { .val = LFS_NEWERXY_OPT,
+                       .name = "newerBa",      .has_arg = required_argument},
+       { .val = LFS_NEWERXY_OPT,
+                       .name = "newerBm",      .has_arg = required_argument},
+       { .val = LFS_NEWERXY_OPT,
+                       .name = "newerBc",      .has_arg = required_argument},
+       { .val = LFS_NEWERXY_OPT,
+                       .name = "newerBB",      .has_arg = required_argument},
+       { .val = LFS_NEWERXY_OPT,
                        .name = "newerat",      .has_arg = required_argument},
        { .val = LFS_NEWERXY_OPT,
                        .name = "newermt",      .has_arg = required_argument},
        { .val = LFS_NEWERXY_OPT,
                        .name = "newerct",      .has_arg = required_argument},
                        .name = "newerat",      .has_arg = required_argument},
        { .val = LFS_NEWERXY_OPT,
                        .name = "newermt",      .has_arg = required_argument},
        { .val = LFS_NEWERXY_OPT,
                        .name = "newerct",      .has_arg = required_argument},
+       { .val = LFS_NEWERXY_OPT,
+                       .name = "newerbt",      .has_arg = required_argument},
+       { .val = LFS_NEWERXY_OPT,
+                       .name = "newerBt",      .has_arg = required_argument},
        { .val = 'c',   .name = "stripe-count", .has_arg = required_argument },
        { .val = 'c',   .name = "stripe_count", .has_arg = required_argument },
        { .val = 'C',   .name = "ctime",        .has_arg = required_argument },
        { .val = 'c',   .name = "stripe-count", .has_arg = required_argument },
        { .val = 'c',   .name = "stripe_count", .has_arg = required_argument },
        { .val = 'C',   .name = "ctime",        .has_arg = required_argument },
@@ -4278,8 +4308,8 @@ static int lfs_find(int argc, char **argv)
 
        /* when getopt_long_only() hits '!' it returns 1, puts "!" in optarg */
        while ((c = getopt_long_only(argc, argv,
 
        /* when getopt_long_only() hits '!' it returns 1, puts "!" in optarg */
        while ((c = getopt_long_only(argc, argv,
-                       "-0A:b:c:C:D:E:g:G:H:i:L:m:M:n:N:O:Ppqrs:S:t:T:u:U:vz:",
-                       long_opts, &optidx)) >= 0) {
+               "-0A:b:B:c:C:D:E:g:G:H:i:L:m:M:n:N:O:Ppqrs:S:t:T:u:U:vz:",
+               long_opts, &optidx)) >= 0) {
                 xtime = NULL;
                 xsign = NULL;
                 if (neg_opt)
                 xtime = NULL;
                 xsign = NULL;
                 if (neg_opt)
@@ -4318,6 +4348,13 @@ static int lfs_find(int argc, char **argv)
                        xtime = &param.fp_atime;
                        xsign = &param.fp_asign;
                        param.fp_exclude_atime = !!neg_opt;
                        xtime = &param.fp_atime;
                        xsign = &param.fp_asign;
                        param.fp_exclude_atime = !!neg_opt;
+                       /* no break, this falls through to 'B' for btime */
+               case 'B':
+                       if (c == 'B') {
+                               xtime = &param.fp_btime;
+                               xsign = &param.fp_bsign;
+                               param.fp_exclude_btime = !!neg_opt;
+                       }
                        /* no break, this falls through to 'C' for ctime */
                case 'C':
                        if (c == 'C') {
                        /* no break, this falls through to 'C' for ctime */
                case 'C':
                        if (c == 'C') {
@@ -4562,6 +4599,24 @@ static int lfs_find(int argc, char **argv)
                                }
 
                                ref = mktime(&tm);
                                }
 
                                ref = mktime(&tm);
+                       } else if (y == 'b' || y == 'B') {
+                               lstatx_t stx;
+
+                               rc = llapi_get_lum_file(optarg, NULL, &stx,
+                                                       NULL, 0);
+                               if (rc || !(stx.stx_mask & STATX_BTIME)) {
+                                       if (!(stx.stx_mask & STATX_BTIME))
+                                               ret = -EOPNOTSUPP;
+                                       else
+                                               ret = -errno;
+                                       fprintf(stderr,
+                                               "%s: get btime failed '%s': %s\n",
+                                               progname, optarg,
+                                               strerror(-ret));
+                                       goto err;
+                               }
+
+                               ref = stx.stx_btime.tv_sec;
                        } else {
                                struct stat statbuf;
 
                        } else {
                                struct stat statbuf;
 
@@ -4603,6 +4658,10 @@ static int lfs_find(int argc, char **argv)
                        case 'c':
                                xidx = NEWERXY_CTIME;
                                break;
                        case 'c':
                                xidx = NEWERXY_CTIME;
                                break;
+                       case 'b':
+                       case 'B':
+                               xidx = NEWERXY_BTIME;
+                               break;
                        default:
                                fprintf(stderr,
                                        "%s: invalid X argument: '%c'\n",
                        default:
                                fprintf(stderr,
                                        "%s: invalid X argument: '%c'\n",
@@ -4974,6 +5033,8 @@ static int lfs_getstripe_internal(int argc, char **argv,
        struct option long_opts[] = {
 /* find        { .val = 'A',   .name = "atime",        .has_arg = required_argument }*/
 /* find        { .val = 'b',   .name = "blocks",       .has_arg = required_argument }*/
        struct option long_opts[] = {
 /* find        { .val = 'A',   .name = "atime",        .has_arg = required_argument }*/
 /* find        { .val = 'b',   .name = "blocks",       .has_arg = required_argument }*/
+/* find        { .val = 'B',   .name = "btime",        .has_arg = required_argument }*/
+/* find        { .val = 'B',   .name = "Btime",        .has_arg = required_argument }*/
        { .val = LFS_COMP_COUNT_OPT,
                        .name = "comp-count",   .has_arg = no_argument },
        { .val = LFS_COMP_COUNT_OPT,
        { .val = LFS_COMP_COUNT_OPT,
                        .name = "comp-count",   .has_arg = no_argument },
        { .val = LFS_COMP_COUNT_OPT,
index 5c0e16b..16e140c 100644 (file)
@@ -4019,7 +4019,7 @@ static int find_time_check(struct find_param *param, int mds)
        return rc;
 }
 
        return rc;
 }
 
-static int find_newerxy_check(struct find_param *param, int mds)
+static int find_newerxy_check(struct find_param *param, int mds, bool from_mdt)
 {
        struct lov_user_mds_data *lmd = param->fp_lmd;
        int i;
 {
        struct lov_user_mds_data *lmd = param->fp_lmd;
        int i;
@@ -4066,6 +4066,27 @@ static int find_newerxy_check(struct find_param *param, int mds)
                        if (rc == 1)
                                rc = rc2;
                }
                        if (rc == 1)
                                rc = rc2;
                }
+
+               /*
+                * File birth time (btime) can get from MDT directly.
+                * if @from_mdt is true, it means the input file attributs are
+                * obtained directly from MDT.
+                * Thus, if @from_mdt is false, we should skip the following
+                * btime check.
+                */
+               if (!from_mdt)
+                       continue;
+
+               if (param->fp_newery[NEWERXY_BTIME][i]) {
+                       if (!(lmd->lmd_stx.stx_mask & STATX_BTIME))
+                               return -EOPNOTSUPP;
+
+                       rc2 = find_value_cmp(lmd->lmd_stx.stx_btime.tv_sec,
+                                            param->fp_newery[NEWERXY_BTIME][i],
+                                            -1, i, 0, 0);
+                       if (rc2 < 0)
+                               return rc2;
+               }
        }
 
        return rc;
        }
 
        return rc;
@@ -4584,7 +4605,8 @@ static int cb_find_init(char *path, DIR *parent, DIR **dirp,
        /* Request MDS for the stat info if some of these parameters need
         * to be compared. */
        if (param->fp_obd_uuid || param->fp_mdt_uuid ||
        /* Request MDS for the stat info if some of these parameters need
         * to be compared. */
        if (param->fp_obd_uuid || param->fp_mdt_uuid ||
-           param->fp_check_uid || param->fp_check_gid || param->fp_newerxy ||
+           param->fp_check_uid || param->fp_check_gid ||
+           param->fp_newerxy || param->fp_btime ||
            param->fp_atime || param->fp_mtime || param->fp_ctime ||
            param->fp_check_size || param->fp_check_blocks ||
            find_check_lmm_info(param) ||
            param->fp_atime || param->fp_mtime || param->fp_ctime ||
            param->fp_check_size || param->fp_check_blocks ||
            find_check_lmm_info(param) ||
@@ -4870,14 +4892,32 @@ obd_matches:
                        goto decided;
        }
 
                        goto decided;
        }
 
+       if (param->fp_btime) {
+               if (!(lmd->lmd_stx.stx_mask & STATX_BTIME)) {
+                       ret = -EOPNOTSUPP;
+                       goto out;
+               }
+
+               decision = find_value_cmp(lmd->lmd_stx.stx_btime.tv_sec,
+                                         param->fp_btime, param->fp_bsign,
+                                         param->fp_exclude_btime,
+                                         param->fp_time_margin, 0);
+               if (decision == -1)
+                       goto decided;
+       }
+
        if (param->fp_newerxy) {
                int for_mds;
 
                for_mds = lustre_fs ?
                          (S_ISREG(lmd->lmd_stx.stx_mode) && stripe_count) : 0;
        if (param->fp_newerxy) {
                int for_mds;
 
                for_mds = lustre_fs ?
                          (S_ISREG(lmd->lmd_stx.stx_mode) && stripe_count) : 0;
-               decision = find_newerxy_check(param, for_mds);
+               decision = find_newerxy_check(param, for_mds, true);
                if (decision == -1)
                        goto decided;
                if (decision == -1)
                        goto decided;
+               if (decision < 0) {
+                       ret = decision;
+                       goto out;
+               }
        }
 
        flags = param->fp_lmd->lmd_flags;
        }
 
        flags = param->fp_lmd->lmd_flags;
@@ -4940,10 +4980,13 @@ obd_matches:
                        goto decided;
 
                if (param->fp_newerxy) {
                        goto decided;
 
                if (param->fp_newerxy) {
-                       decision = find_newerxy_check(param, 0);
+                       decision = find_newerxy_check(param, 0, false);
                        if (decision == -1)
                                goto decided;
                        if (decision == -1)
                                goto decided;
-
+                       if (decision < 0) {
+                               ret = decision;
+                               goto out;
+                       }
                }
        }
 
                }
        }
 
index c2cd0ad..5dfd6f4 100644 (file)
@@ -3426,7 +3426,9 @@ int llapi_get_lum_file_fd(int dir_fd, const char *fname, __u64 *valid,
        if (rc)
                return rc;
 
        if (rc)
                return rc;
 
-       *valid = lmd->lmd_flags;
+       if (valid)
+               *valid = lmd->lmd_flags;
+
        if (statx)
                memcpy(statx, &lmd->lmd_stx, sizeof(*statx));
 
        if (statx)
                memcpy(statx, &lmd->lmd_stx, sizeof(*statx));
 
index cadc201..3c9a431 100644 (file)
@@ -2519,10 +2519,10 @@ void lustre_assert_wire_constants(void)
                 (long long)(int)offsetof(struct mdt_body, mbo_dom_blocks));
        LASSERTF((int)sizeof(((struct mdt_body *)0)->mbo_dom_blocks) == 8, "found %lld\n",
                 (long long)(int)sizeof(((struct mdt_body *)0)->mbo_dom_blocks));
                 (long long)(int)offsetof(struct mdt_body, mbo_dom_blocks));
        LASSERTF((int)sizeof(((struct mdt_body *)0)->mbo_dom_blocks) == 8, "found %lld\n",
                 (long long)(int)sizeof(((struct mdt_body *)0)->mbo_dom_blocks));
-       LASSERTF((int)offsetof(struct mdt_body, mbo_padding_8) == 192, "found %lld\n",
-                (long long)(int)offsetof(struct mdt_body, mbo_padding_8));
-       LASSERTF((int)sizeof(((struct mdt_body *)0)->mbo_padding_8) == 8, "found %lld\n",
-                (long long)(int)sizeof(((struct mdt_body *)0)->mbo_padding_8));
+       LASSERTF((int)offsetof(struct mdt_body, mbo_btime) == 192, "found %lld\n",
+                (long long)(int)offsetof(struct mdt_body, mbo_btime));
+       LASSERTF((int)sizeof(((struct mdt_body *)0)->mbo_btime) == 8, "found %lld\n",
+                (long long)(int)sizeof(((struct mdt_body *)0)->mbo_btime));
        LASSERTF((int)offsetof(struct mdt_body, mbo_padding_9) == 200, "found %lld\n",
                 (long long)(int)offsetof(struct mdt_body, mbo_padding_9));
        LASSERTF((int)sizeof(((struct mdt_body *)0)->mbo_padding_9) == 8, "found %lld\n",
        LASSERTF((int)offsetof(struct mdt_body, mbo_padding_9) == 200, "found %lld\n",
                 (long long)(int)offsetof(struct mdt_body, mbo_padding_9));
        LASSERTF((int)sizeof(((struct mdt_body *)0)->mbo_padding_9) == 8, "found %lld\n",