]> granicus.if.org Git - zfs/commitdiff
Linux 4.18 compat: inode timespec -> timespec64
authorBrian Behlendorf <behlendorf1@llnl.gov>
Sun, 12 Aug 2018 22:22:03 +0000 (18:22 -0400)
committerTony Hutter <hutter2@llnl.gov>
Fri, 6 Jul 2018 09:46:51 +0000 (02:46 -0700)
Commit torvalds/linux@95582b0 changes the inode i_atime, i_mtime,
and i_ctime members form timespec's to timespec64's to make them
2038 safe.  As part of this change the current_time() function was
also updated to return the timespec64 type.

Resolve this issue by introducing a new inode_timespec_t type which
is defined to match the timespec type used by the inode.  It should
be used when working with inode timestamps to ensure matching types.

The timestruc_t type under Illumos was used in a similar fashion but
was specified to always be a timespec_t.  Rather than incorrectly
define this type all timespec_t types have been replaced by the new
inode_timespec_t type.

Finally, the kernel and user space 'sys/time.h' headers were aligned
with each other.  They define as appropriate for the context several
constants as macros and include static inline implementation of
gethrestime(), gethrestime_sec(), and gethrtime().

Reviewed-by: Chunwei Chen <tuxoko@gmail.com>
Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov>
Closes #7643
Backported-by: Richard Yao <ryao@gentoo.org>
21 files changed:
config/kernel-current-time.m4
include/sys/dmu.h
include/sys/dmu_objset.h
include/sys/dsl_dir.h
include/sys/spa_impl.h
include/sys/xvattr.h
include/sys/zfs_context.h
include/sys/zfs_znode.h
include/sys/zpl.h
lib/libspl/Makefile.am
lib/libspl/gethrestime.c [deleted file]
lib/libspl/gethrtime.c [deleted file]
lib/libspl/include/sys/time.h
lib/libzpool/kernel.c
module/zfs/dmu_objset.c
module/zfs/dsl_dir.c
module/zfs/fm.c
module/zfs/zfs_ctldir.c
module/zfs/zfs_vnops.c
module/zfs/zfs_znode.c
module/zfs/zpl_inode.c

index 2ede9ff38c4165a1c8d1708ac61878e9ae701af3..c7d5c9b52006da39cf493afb58e663da885eca17 100644 (file)
@@ -1,15 +1,14 @@
 dnl #
 dnl # 4.9, current_time() added
+dnl # 4.18, return type changed from timespec to timespec64
 dnl #
 AC_DEFUN([ZFS_AC_KERNEL_CURRENT_TIME],
        [AC_MSG_CHECKING([whether current_time() exists])
        ZFS_LINUX_TRY_COMPILE_SYMBOL([
                #include <linux/fs.h>
        ], [
-               struct inode ip;
-               struct timespec now __attribute__ ((unused));
-
-               now = current_time(&ip);
+               struct inode ip __attribute__ ((unused));
+               ip.i_atime = current_time(&ip);
        ], [current_time], [fs/inode.c], [
                AC_MSG_RESULT(yes)
                AC_DEFINE(HAVE_CURRENT_TIME, 1, [current_time() exists])
index bcdf7d646fbc8073337a412c4ac1772753a2cc39..755a90561ae5313b3e6e84d97d6c64281eca672e 100644 (file)
@@ -891,7 +891,7 @@ uint64_t dmu_objset_fsid_guid(objset_t *os);
 /*
  * Get the [cm]time for an objset's snapshot dir
  */
-timestruc_t dmu_objset_snap_cmtime(objset_t *os);
+inode_timespec_t dmu_objset_snap_cmtime(objset_t *os);
 
 int dmu_objset_is_snapshot(objset_t *os);
 
index a836e03722c32fa9feffbce170cb2d73b3be9b11..531e81d4d88058e6af4893d4c6faaa26ef7e61c7 100644 (file)
@@ -179,7 +179,7 @@ int dmu_objset_find_dp(struct dsl_pool *dp, uint64_t ddobj,
     int func(struct dsl_pool *, struct dsl_dataset *, void *),
     void *arg, int flags);
 void dmu_objset_evict_dbufs(objset_t *os);
-timestruc_t dmu_objset_snap_cmtime(objset_t *os);
+inode_timespec_t dmu_objset_snap_cmtime(objset_t *os);
 
 /* called from dsl */
 void dmu_objset_sync(objset_t *os, zio_t *zio, dmu_tx_t *tx);
index 69b0b6a53559d2aa5a473701762042b94431826a..80e83fdc4d37a6bc6b58d785db5a84be9b179318 100644 (file)
@@ -103,7 +103,7 @@ struct dsl_dir {
        /* Protected by dd_lock */
        kmutex_t dd_lock;
        list_t dd_props; /* list of dsl_prop_record_t's */
-       timestruc_t dd_snap_cmtime; /* last time snapshot namespace changed */
+       inode_timespec_t dd_snap_cmtime; /* last snapshot namespace change */
        uint64_t dd_origin_txg;
 
        /* gross estimate of space used by in-flight tx's */
@@ -159,7 +159,7 @@ boolean_t dsl_dir_is_clone(dsl_dir_t *dd);
 void dsl_dir_new_refreservation(dsl_dir_t *dd, struct dsl_dataset *ds,
     uint64_t reservation, cred_t *cr, dmu_tx_t *tx);
 void dsl_dir_snap_cmtime_update(dsl_dir_t *dd);
-timestruc_t dsl_dir_snap_cmtime(dsl_dir_t *dd);
+inode_timespec_t dsl_dir_snap_cmtime(dsl_dir_t *dd);
 void dsl_dir_set_reservation_sync_impl(dsl_dir_t *dd, uint64_t value,
     dmu_tx_t *tx);
 void dsl_dir_zapify(dsl_dir_t *dd, dmu_tx_t *tx);
index b1e78c1d592b187048c62f5200975cb0ede906b9..fa7490ace673831a41e323b2fdd0722ef3f9da81 100644 (file)
@@ -153,7 +153,7 @@ struct spa {
        uint64_t        spa_freeze_txg;         /* freeze pool at this txg */
        uint64_t        spa_load_max_txg;       /* best initial ub_txg */
        uint64_t        spa_claim_max_txg;      /* highest claimed birth txg */
-       timespec_t      spa_loaded_ts;          /* 1st successful open time */
+       inode_timespec_t spa_loaded_ts;         /* 1st successful open time */
        objset_t        *spa_meta_objset;       /* copy of dp->dp_meta_objset */
        kmutex_t        spa_evicting_os_lock;   /* Evicting objset list lock */
        list_t          spa_evicting_os_list;   /* Objsets being evicted. */
index 4779b632163f33b84b18a881c4d24c73975ca1c9..5d38927cd4bb9e30cd0b4450d9d1ed2ade69dd0f 100644 (file)
@@ -47,7 +47,7 @@
  * Structure of all optional attributes.
  */
 typedef struct xoptattr {
-       timestruc_t     xoa_createtime; /* Create time of file */
+       inode_timespec_t xoa_createtime;        /* Create time of file */
        uint8_t         xoa_archive;
        uint8_t         xoa_system;
        uint8_t         xoa_readonly;
index 4fe35342dee78336db8847db59f19f6338659f23..68c58f955311b61ea42be392b6db8ac9de386695 100644 (file)
@@ -527,7 +527,7 @@ extern char *vn_dumpdir;
 #define        AV_SCANSTAMP_SZ 32              /* length of anti-virus scanstamp */
 
 typedef struct xoptattr {
-       timestruc_t     xoa_createtime; /* Create time of file */
+       inode_timespec_t xoa_createtime;        /* Create time of file */
        uint8_t         xoa_archive;
        uint8_t         xoa_system;
        uint8_t         xoa_readonly;
@@ -640,13 +640,6 @@ extern void delay(clock_t ticks);
 #define        USEC_TO_TICK(usec)      ((usec) / (MICROSEC / hz))
 #define        NSEC_TO_TICK(usec)      ((usec) / (NANOSEC / hz))
 
-#define        gethrestime_sec() time(NULL)
-#define        gethrestime(t) \
-       do {\
-               (t)->tv_sec = gethrestime_sec();\
-               (t)->tv_nsec = 0;\
-       } while (0);
-
 #define        max_ncpus       64
 #define        boot_ncpus      (sysconf(_SC_NPROCESSORS_ONLN))
 
index c292f03739e34de2a3e1c72a5dbb42acd60c815c..26d1eb37557c5311f911f83bc25202183d69fe94 100644 (file)
@@ -270,19 +270,36 @@ typedef struct znode_hold {
 
 extern unsigned int zfs_object_mutex_size;
 
-/* Encode ZFS stored time values from a struct timespec */
+/*
+ * Encode ZFS stored time values from a struct timespec / struct timespec64.
+ */
 #define        ZFS_TIME_ENCODE(tp, stmp)               \
-{                                              \
+do {                                           \
        (stmp)[0] = (uint64_t)(tp)->tv_sec;     \
        (stmp)[1] = (uint64_t)(tp)->tv_nsec;    \
-}
+} while (0)
 
-/* Decode ZFS stored time values to a struct timespec */
+#if defined(HAVE_INODE_TIMESPEC64_TIMES)
+/*
+ * Decode ZFS stored time values to a struct timespec64
+ * 4.18 and newer kernels.
+ */
 #define        ZFS_TIME_DECODE(tp, stmp)               \
-{                                              \
-       (tp)->tv_sec = (time_t)(stmp)[0];               \
-       (tp)->tv_nsec = (long)(stmp)[1];                \
-}
+do {                                           \
+       (tp)->tv_sec = (time64_t)(stmp)[0];     \
+       (tp)->tv_nsec = (long)(stmp)[1];        \
+} while (0)
+#else
+/*
+ * Decode ZFS stored time values to a struct timespec
+ * 4.17 and older kernels.
+ */
+#define        ZFS_TIME_DECODE(tp, stmp)               \
+do {                                           \
+       (tp)->tv_sec = (time_t)(stmp)[0];       \
+       (tp)->tv_nsec = (long)(stmp)[1];        \
+} while (0)
+#endif /* HAVE_INODE_TIMESPEC64_TIMES */
 
 /*
  * Timestamp defines
index 65ed4313603545988644cf67065f78d8e914d99f..e433fbc64ea03648c1ed57c775dc22e5a2aa3a45 100644 (file)
@@ -189,4 +189,13 @@ zpl_dir_emit_dots(struct file *file, zpl_dir_context_t *ctx)
 }
 #endif /* HAVE_VFS_ITERATE */
 
+/*
+ * Linux 4.18, inode times converted from timespec to timespec64.
+ */
+#if defined(HAVE_INODE_TIMESPEC64_TIMES)
+#define        zpl_inode_timespec_trunc(ts, gran)      timespec64_trunc(ts, gran)
+#else
+#define        zpl_inode_timespec_trunc(ts, gran)      timespec_trunc(ts, gran)
+#endif
+
 #endif /* _SYS_ZPL_H */
index 59bc8ffb42fbf4cc304e79fc54aa724d67184ad1..a6e63cb8868b93db0ee2726a31b06b88129f001c 100644 (file)
@@ -19,8 +19,6 @@ noinst_LTLIBRARIES = libspl.la
 
 USER_C = \
        getexecname.c \
-       gethrtime.c \
-       gethrestime.c \
        getmntany.c \
        list.c \
        mkdirp.c \
diff --git a/lib/libspl/gethrestime.c b/lib/libspl/gethrestime.c
deleted file mode 100644 (file)
index d37cc2d..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-
-/*
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
- */
-
-#include <time.h>
-#include <sys/time.h>
-
-void
-gethrestime(timestruc_t *ts)
-{
-       struct timeval tv;
-
-       gettimeofday(&tv, NULL);
-       ts->tv_sec = tv.tv_sec;
-       ts->tv_nsec = tv.tv_usec * NSEC_PER_USEC;
-}
diff --git a/lib/libspl/gethrtime.c b/lib/libspl/gethrtime.c
deleted file mode 100644 (file)
index 95ceb18..0000000
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-
-/*
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
- */
-
-#include <time.h>
-#include <sys/time.h>
-#include <stdlib.h>
-#include <stdio.h>
-
-hrtime_t
-gethrtime(void)
-{
-       struct timespec ts;
-       int rc;
-
-       rc = clock_gettime(CLOCK_MONOTONIC, &ts);
-       if (rc) {
-               fprintf(stderr, "Error: clock_gettime() = %d\n", rc);
-               abort();
-       }
-
-       return ((((u_int64_t)ts.tv_sec) * NANOSEC) + ts.tv_nsec);
-}
index dc645fa5c370ff71c5c2acb46cd39b0d98250345..04b3ba87bd36b5ae9c6b61f6fb4336d47a88f092 100644 (file)
@@ -27,8 +27,9 @@
 #ifndef _LIBSPL_SYS_TIME_H
 #define        _LIBSPL_SYS_TIME_H
 
-#include_next <sys/time.h>
+#include <time.h>
 #include <sys/types.h>
+#include_next <sys/time.h>
 
 #ifndef SEC
 #define        SEC             1
 #define        SEC2NSEC(m)     ((hrtime_t)(m) * (NANOSEC / SEC))
 #endif
 
-
 typedef        long long               hrtime_t;
-typedef        struct  timespec        timestruc_t;
-typedef        struct  timespec        timespec_t;
-
-
-extern hrtime_t gethrtime(void);
-extern void gethrestime(timestruc_t *);
+typedef        struct timespec         timespec_t;
+typedef struct timespec                inode_timespec_t;
+
+static inline void
+gethrestime(inode_timespec_t *ts)
+{
+       struct timeval tv;
+       (void) gettimeofday(&tv, NULL);
+       ts->tv_sec = tv.tv_sec;
+       ts->tv_nsec = tv.tv_usec * NSEC_PER_USEC;
+}
+
+static inline time_t
+gethrestime_sec(void)
+{
+       struct timeval tv;
+       (void) gettimeofday(&tv, NULL);
+       return (tv.tv_sec);
+}
+
+static inline hrtime_t
+gethrtime(void)
+{
+       struct timespec ts;
+       (void) clock_gettime(CLOCK_MONOTONIC, &ts);
+       return ((((u_int64_t)ts.tv_sec) * NANOSEC) + ts.tv_nsec);
+}
 
 #endif /* _LIBSPL_SYS_TIME_H */
index e67d13c9265270dffc6fe41507b3c0d42df7ea37..3ea8778b1dc82a193e39587e7f9820fa6bae022e 100644 (file)
@@ -498,7 +498,7 @@ cv_timedwait(kcondvar_t *cv, kmutex_t *mp, clock_t abstime)
 {
        int error;
        struct timeval tv;
-       timestruc_t ts;
+       struct timespec ts;
        clock_t delta;
 
        ASSERT3U(cv->cv_magic, ==, CV_MAGIC);
@@ -536,7 +536,7 @@ cv_timedwait_hires(kcondvar_t *cv, kmutex_t *mp, hrtime_t tim, hrtime_t res,
 {
        int error;
        struct timeval tv;
-       timestruc_t ts;
+       struct timespec ts;
        hrtime_t delta;
 
        ASSERT(flag == 0 || flag == CALLOUT_FLAG_ABSOLUTE);
index 3425d542f98327bd51796e08d5336e724e889aa6..449ebedfa1654182aa06404d3f5ee0085997e33d 100644 (file)
@@ -860,7 +860,7 @@ dmu_objset_evict_done(objset_t *os)
        kmem_free(os, sizeof (objset_t));
 }
 
-timestruc_t
+inode_timespec_t
 dmu_objset_snap_cmtime(objset_t *os)
 {
        return (dsl_dir_snap_cmtime(os->os_dsl_dataset->ds_dir));
index a3ef5896a3f22704f574b2e4aaacc14f098f8f98..deecf6bc53ee4abb5621486889c3f0c66a78dd12 100644 (file)
@@ -1975,10 +1975,10 @@ dsl_dir_transfer_possible(dsl_dir_t *sdd, dsl_dir_t *tdd,
        return (0);
 }
 
-timestruc_t
+inode_timespec_t
 dsl_dir_snap_cmtime(dsl_dir_t *dd)
 {
-       timestruc_t t;
+       inode_timespec_t t;
 
        mutex_enter(&dd->dd_lock);
        t = dd->dd_snap_cmtime;
@@ -1990,7 +1990,7 @@ dsl_dir_snap_cmtime(dsl_dir_t *dd)
 void
 dsl_dir_snap_cmtime_update(dsl_dir_t *dd)
 {
-       timestruc_t t;
+       inode_timespec_t t;
 
        gethrestime(&t);
        mutex_enter(&dd->dd_lock);
index cb148149376bebcb6e962cbc242df23bf97787d2..9d26cc99eeb68814334841a24f02eb22096aa5e5 100644 (file)
@@ -508,8 +508,8 @@ zfs_zevent_insert(zevent_t *ev)
 int
 zfs_zevent_post(nvlist_t *nvl, nvlist_t *detector, zevent_cb_t *cb)
 {
+       inode_timespec_t tv;
        int64_t tv_array[2];
-       timestruc_t tv;
        uint64_t eid;
        size_t nvl_size = 0;
        zevent_t *ev;
index 3b5fb196f1d4171f8650996f9145393b4665efa4..3ff2c101b67b74808096b579a2c206138d5490dd 100644 (file)
@@ -451,7 +451,7 @@ static struct inode *
 zfsctl_inode_alloc(zfsvfs_t *zfsvfs, uint64_t id,
     const struct file_operations *fops, const struct inode_operations *ops)
 {
-       struct timespec now;
+       inode_timespec_t now;
        struct inode *ip;
        znode_t *zp;
 
index 0d2b61a1c31c6c0983990ea9fee870e70e698863..34ea751c32071dbc6e92c6ef16cb41c123b61d92 100644 (file)
@@ -3158,7 +3158,7 @@ top:
 
        if (mask & (ATTR_MTIME | ATTR_SIZE)) {
                ZFS_TIME_ENCODE(&vap->va_mtime, mtime);
-               ZTOI(zp)->i_mtime = timespec_trunc(vap->va_mtime,
+               ZTOI(zp)->i_mtime = zpl_inode_timespec_trunc(vap->va_mtime,
                    ZTOI(zp)->i_sb->s_time_gran);
 
                SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_MTIME(zfsvfs), NULL,
@@ -3167,7 +3167,7 @@ top:
 
        if (mask & (ATTR_CTIME | ATTR_SIZE)) {
                ZFS_TIME_ENCODE(&vap->va_ctime, ctime);
-               ZTOI(zp)->i_ctime = timespec_trunc(vap->va_ctime,
+               ZTOI(zp)->i_ctime = zpl_inode_timespec_trunc(vap->va_ctime,
                    ZTOI(zp)->i_sb->s_time_gran);
                SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_CTIME(zfsvfs), NULL,
                    ctime, sizeof (ctime));
index f508a248f0f7b9a4a737ee9421120871e4ebeb85..e222c791183469f78265ce0a36cff42c9a784ad7 100644 (file)
@@ -700,7 +700,7 @@ zfs_mknode(znode_t *dzp, vattr_t *vap, dmu_tx_t *tx, cred_t *cr,
        uint64_t        rdev = 0;
        zfsvfs_t        *zfsvfs = ZTOZSB(dzp);
        dmu_buf_t       *db;
-       timestruc_t     now;
+       inode_timespec_t now;
        uint64_t        gen, obj;
        int             bonuslen;
        int             dnodesize;
@@ -1349,7 +1349,7 @@ void
 zfs_tstamp_update_setup(znode_t *zp, uint_t flag, uint64_t mtime[2],
     uint64_t ctime[2])
 {
-       timestruc_t     now;
+       inode_timespec_t now;
 
        gethrestime(&now);
 
index 3b5643d09177944ed80f877605e6ca0f91bf55bb..41b91cabcb9689a428843175043a5c7e70063b05 100644 (file)
@@ -384,9 +384,10 @@ zpl_setattr(struct dentry *dentry, struct iattr *ia)
        vap->va_mtime = ia->ia_mtime;
        vap->va_ctime = ia->ia_ctime;
 
-       if (vap->va_mask & ATTR_ATIME)
-               ip->i_atime = timespec_trunc(ia->ia_atime,
+       if (vap->va_mask & ATTR_ATIME) {
+               ip->i_atime = zpl_inode_timespec_trunc(ia->ia_atime,
                    ip->i_sb->s_time_gran);
+       }
 
        cookie = spl_fstrans_mark();
        error = -zfs_setattr(ip, vap, 0, cr);