1 From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
2 From: Brian Behlendorf <behlendorf1@llnl.gov>
3 Date: Sun, 12 Aug 2018 18:22:03 -0400
4 Subject: [PATCH] Linux 4.18 compat: inode timespec -> timespec64
6 Commit torvalds/linux@95582b0 changes the inode i_atime, i_mtime,
7 and i_ctime members form timespec's to timespec64's to make them
8 2038 safe. As part of this change the current_time() function was
9 also updated to return the timespec64 type.
11 Resolve this issue by introducing a new inode_timespec_t type which
12 is defined to match the timespec type used by the inode. It should
13 be used when working with inode timestamps to ensure matching types.
15 The timestruc_t type under Illumos was used in a similar fashion but
16 was specified to always be a timespec_t. Rather than incorrectly
17 define this type all timespec_t types have been replaced by the new
18 inode_timespec_t type.
20 Finally, the kernel and user space 'sys/time.h' headers were aligned
21 with each other. They define as appropriate for the context several
22 constants as macros and include static inline implementation of
23 gethrestime(), gethrestime_sec(), and gethrtime().
25 Reviewed-by: Chunwei Chen <tuxoko@gmail.com>
26 Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov>
28 Backported-by: Richard Yao <ryao@gentoo.org>
30 Signed-off-by: Stoiko Ivanov <s.ivanov@proxmox.com>
32 config/kernel-current-time.m4 | 7 +++----
33 include/sys/dmu.h | 2 +-
34 include/sys/dmu_objset.h | 2 +-
35 include/sys/dsl_dir.h | 4 ++--
36 include/sys/spa_impl.h | 2 +-
37 include/sys/xvattr.h | 2 +-
38 include/sys/zfs_context.h | 9 +--------
39 include/sys/zfs_znode.h | 33 +++++++++++++++++++++++--------
40 include/sys/zpl.h | 9 +++++++++
41 lib/libspl/Makefile.am | 2 --
42 lib/libspl/gethrestime.c | 38 ------------------------------------
43 lib/libspl/gethrtime.c | 45 -------------------------------------------
44 lib/libspl/include/sys/time.h | 37 +++++++++++++++++++++++++++--------
45 lib/libzpool/kernel.c | 4 ++--
46 module/zfs/dmu_objset.c | 2 +-
47 module/zfs/dsl_dir.c | 6 +++---
48 module/zfs/fm.c | 2 +-
49 module/zfs/zfs_ctldir.c | 2 +-
50 module/zfs/zfs_vnops.c | 4 ++--
51 module/zfs/zfs_znode.c | 4 ++--
52 module/zfs/zpl_inode.c | 5 +++--
53 21 files changed, 88 insertions(+), 133 deletions(-)
54 delete mode 100644 lib/libspl/gethrestime.c
55 delete mode 100644 lib/libspl/gethrtime.c
57 diff --git a/config/kernel-current-time.m4 b/config/kernel-current-time.m4
58 index 2ede9ff3..c7d5c9b5 100644
59 --- a/config/kernel-current-time.m4
60 +++ b/config/kernel-current-time.m4
63 dnl # 4.9, current_time() added
64 +dnl # 4.18, return type changed from timespec to timespec64
66 AC_DEFUN([ZFS_AC_KERNEL_CURRENT_TIME],
67 [AC_MSG_CHECKING([whether current_time() exists])
68 ZFS_LINUX_TRY_COMPILE_SYMBOL([
72 - struct timespec now __attribute__ ((unused));
74 - now = current_time(&ip);
75 + struct inode ip __attribute__ ((unused));
76 + ip.i_atime = current_time(&ip);
77 ], [current_time], [fs/inode.c], [
79 AC_DEFINE(HAVE_CURRENT_TIME, 1, [current_time() exists])
80 diff --git a/include/sys/dmu.h b/include/sys/dmu.h
81 index bcdf7d64..755a9056 100644
82 --- a/include/sys/dmu.h
83 +++ b/include/sys/dmu.h
84 @@ -891,7 +891,7 @@ uint64_t dmu_objset_fsid_guid(objset_t *os);
86 * Get the [cm]time for an objset's snapshot dir
88 -timestruc_t dmu_objset_snap_cmtime(objset_t *os);
89 +inode_timespec_t dmu_objset_snap_cmtime(objset_t *os);
91 int dmu_objset_is_snapshot(objset_t *os);
93 diff --git a/include/sys/dmu_objset.h b/include/sys/dmu_objset.h
94 index a836e037..531e81d4 100644
95 --- a/include/sys/dmu_objset.h
96 +++ b/include/sys/dmu_objset.h
97 @@ -179,7 +179,7 @@ int dmu_objset_find_dp(struct dsl_pool *dp, uint64_t ddobj,
98 int func(struct dsl_pool *, struct dsl_dataset *, void *),
99 void *arg, int flags);
100 void dmu_objset_evict_dbufs(objset_t *os);
101 -timestruc_t dmu_objset_snap_cmtime(objset_t *os);
102 +inode_timespec_t dmu_objset_snap_cmtime(objset_t *os);
104 /* called from dsl */
105 void dmu_objset_sync(objset_t *os, zio_t *zio, dmu_tx_t *tx);
106 diff --git a/include/sys/dsl_dir.h b/include/sys/dsl_dir.h
107 index 69b0b6a5..80e83fdc 100644
108 --- a/include/sys/dsl_dir.h
109 +++ b/include/sys/dsl_dir.h
110 @@ -103,7 +103,7 @@ struct dsl_dir {
111 /* Protected by dd_lock */
113 list_t dd_props; /* list of dsl_prop_record_t's */
114 - timestruc_t dd_snap_cmtime; /* last time snapshot namespace changed */
115 + inode_timespec_t dd_snap_cmtime; /* last snapshot namespace change */
116 uint64_t dd_origin_txg;
118 /* gross estimate of space used by in-flight tx's */
119 @@ -159,7 +159,7 @@ boolean_t dsl_dir_is_clone(dsl_dir_t *dd);
120 void dsl_dir_new_refreservation(dsl_dir_t *dd, struct dsl_dataset *ds,
121 uint64_t reservation, cred_t *cr, dmu_tx_t *tx);
122 void dsl_dir_snap_cmtime_update(dsl_dir_t *dd);
123 -timestruc_t dsl_dir_snap_cmtime(dsl_dir_t *dd);
124 +inode_timespec_t dsl_dir_snap_cmtime(dsl_dir_t *dd);
125 void dsl_dir_set_reservation_sync_impl(dsl_dir_t *dd, uint64_t value,
127 void dsl_dir_zapify(dsl_dir_t *dd, dmu_tx_t *tx);
128 diff --git a/include/sys/spa_impl.h b/include/sys/spa_impl.h
129 index b1e78c1d..fa7490ac 100644
130 --- a/include/sys/spa_impl.h
131 +++ b/include/sys/spa_impl.h
132 @@ -153,7 +153,7 @@ struct spa {
133 uint64_t spa_freeze_txg; /* freeze pool at this txg */
134 uint64_t spa_load_max_txg; /* best initial ub_txg */
135 uint64_t spa_claim_max_txg; /* highest claimed birth txg */
136 - timespec_t spa_loaded_ts; /* 1st successful open time */
137 + inode_timespec_t spa_loaded_ts; /* 1st successful open time */
138 objset_t *spa_meta_objset; /* copy of dp->dp_meta_objset */
139 kmutex_t spa_evicting_os_lock; /* Evicting objset list lock */
140 list_t spa_evicting_os_list; /* Objsets being evicted. */
141 diff --git a/include/sys/xvattr.h b/include/sys/xvattr.h
142 index 4779b632..5d38927c 100644
143 --- a/include/sys/xvattr.h
144 +++ b/include/sys/xvattr.h
146 * Structure of all optional attributes.
148 typedef struct xoptattr {
149 - timestruc_t xoa_createtime; /* Create time of file */
150 + inode_timespec_t xoa_createtime; /* Create time of file */
153 uint8_t xoa_readonly;
154 diff --git a/include/sys/zfs_context.h b/include/sys/zfs_context.h
155 index 4fe35342..68c58f95 100644
156 --- a/include/sys/zfs_context.h
157 +++ b/include/sys/zfs_context.h
158 @@ -527,7 +527,7 @@ extern char *vn_dumpdir;
159 #define AV_SCANSTAMP_SZ 32 /* length of anti-virus scanstamp */
161 typedef struct xoptattr {
162 - timestruc_t xoa_createtime; /* Create time of file */
163 + inode_timespec_t xoa_createtime; /* Create time of file */
166 uint8_t xoa_readonly;
167 @@ -640,13 +640,6 @@ extern void delay(clock_t ticks);
168 #define USEC_TO_TICK(usec) ((usec) / (MICROSEC / hz))
169 #define NSEC_TO_TICK(usec) ((usec) / (NANOSEC / hz))
171 -#define gethrestime_sec() time(NULL)
172 -#define gethrestime(t) \
174 - (t)->tv_sec = gethrestime_sec();\
179 #define boot_ncpus (sysconf(_SC_NPROCESSORS_ONLN))
181 diff --git a/include/sys/zfs_znode.h b/include/sys/zfs_znode.h
182 index c292f037..26d1eb37 100644
183 --- a/include/sys/zfs_znode.h
184 +++ b/include/sys/zfs_znode.h
185 @@ -270,19 +270,36 @@ typedef struct znode_hold {
187 extern unsigned int zfs_object_mutex_size;
189 -/* Encode ZFS stored time values from a struct timespec */
191 + * Encode ZFS stored time values from a struct timespec / struct timespec64.
193 #define ZFS_TIME_ENCODE(tp, stmp) \
196 (stmp)[0] = (uint64_t)(tp)->tv_sec; \
197 (stmp)[1] = (uint64_t)(tp)->tv_nsec; \
201 -/* Decode ZFS stored time values to a struct timespec */
202 +#if defined(HAVE_INODE_TIMESPEC64_TIMES)
204 + * Decode ZFS stored time values to a struct timespec64
205 + * 4.18 and newer kernels.
207 #define ZFS_TIME_DECODE(tp, stmp) \
209 - (tp)->tv_sec = (time_t)(stmp)[0]; \
210 - (tp)->tv_nsec = (long)(stmp)[1]; \
213 + (tp)->tv_sec = (time64_t)(stmp)[0]; \
214 + (tp)->tv_nsec = (long)(stmp)[1]; \
218 + * Decode ZFS stored time values to a struct timespec
219 + * 4.17 and older kernels.
221 +#define ZFS_TIME_DECODE(tp, stmp) \
223 + (tp)->tv_sec = (time_t)(stmp)[0]; \
224 + (tp)->tv_nsec = (long)(stmp)[1]; \
226 +#endif /* HAVE_INODE_TIMESPEC64_TIMES */
230 diff --git a/include/sys/zpl.h b/include/sys/zpl.h
231 index 65ed4313..e433fbc6 100644
232 --- a/include/sys/zpl.h
233 +++ b/include/sys/zpl.h
234 @@ -189,4 +189,13 @@ zpl_dir_emit_dots(struct file *file, zpl_dir_context_t *ctx)
236 #endif /* HAVE_VFS_ITERATE */
239 + * Linux 4.18, inode times converted from timespec to timespec64.
241 +#if defined(HAVE_INODE_TIMESPEC64_TIMES)
242 +#define zpl_inode_timespec_trunc(ts, gran) timespec64_trunc(ts, gran)
244 +#define zpl_inode_timespec_trunc(ts, gran) timespec_trunc(ts, gran)
247 #endif /* _SYS_ZPL_H */
248 diff --git a/lib/libspl/Makefile.am b/lib/libspl/Makefile.am
249 index 59bc8ffb..a6e63cb8 100644
250 --- a/lib/libspl/Makefile.am
251 +++ b/lib/libspl/Makefile.am
252 @@ -19,8 +19,6 @@ noinst_LTLIBRARIES = libspl.la
261 diff --git a/lib/libspl/gethrestime.c b/lib/libspl/gethrestime.c
262 deleted file mode 100644
263 index d37cc2d5..00000000
264 --- a/lib/libspl/gethrestime.c
268 - * CDDL HEADER START
270 - * The contents of this file are subject to the terms of the
271 - * Common Development and Distribution License (the "License").
272 - * You may not use this file except in compliance with the License.
274 - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
275 - * or http://www.opensolaris.org/os/licensing.
276 - * See the License for the specific language governing permissions
277 - * and limitations under the License.
279 - * When distributing Covered Code, include this CDDL HEADER in each
280 - * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
281 - * If applicable, add the following below this CDDL HEADER, with the
282 - * fields enclosed by brackets "[]" replaced with your own identifying
283 - * information: Portions Copyright [yyyy] [name of copyright owner]
289 - * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
290 - * Use is subject to license terms.
294 -#include <sys/time.h>
297 -gethrestime(timestruc_t *ts)
301 - gettimeofday(&tv, NULL);
302 - ts->tv_sec = tv.tv_sec;
303 - ts->tv_nsec = tv.tv_usec * NSEC_PER_USEC;
305 diff --git a/lib/libspl/gethrtime.c b/lib/libspl/gethrtime.c
306 deleted file mode 100644
307 index 95ceb18e..00000000
308 --- a/lib/libspl/gethrtime.c
312 - * CDDL HEADER START
314 - * The contents of this file are subject to the terms of the
315 - * Common Development and Distribution License (the "License").
316 - * You may not use this file except in compliance with the License.
318 - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
319 - * or http://www.opensolaris.org/os/licensing.
320 - * See the License for the specific language governing permissions
321 - * and limitations under the License.
323 - * When distributing Covered Code, include this CDDL HEADER in each
324 - * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
325 - * If applicable, add the following below this CDDL HEADER, with the
326 - * fields enclosed by brackets "[]" replaced with your own identifying
327 - * information: Portions Copyright [yyyy] [name of copyright owner]
333 - * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
334 - * Use is subject to license terms.
338 -#include <sys/time.h>
345 - struct timespec ts;
348 - rc = clock_gettime(CLOCK_MONOTONIC, &ts);
350 - fprintf(stderr, "Error: clock_gettime() = %d\n", rc);
354 - return ((((u_int64_t)ts.tv_sec) * NANOSEC) + ts.tv_nsec);
356 diff --git a/lib/libspl/include/sys/time.h b/lib/libspl/include/sys/time.h
357 index dc645fa5..04b3ba87 100644
358 --- a/lib/libspl/include/sys/time.h
359 +++ b/lib/libspl/include/sys/time.h
361 #ifndef _LIBSPL_SYS_TIME_H
362 #define _LIBSPL_SYS_TIME_H
364 -#include_next <sys/time.h>
366 #include <sys/types.h>
367 +#include_next <sys/time.h>
372 #define SEC2NSEC(m) ((hrtime_t)(m) * (NANOSEC / SEC))
376 typedef long long hrtime_t;
377 -typedef struct timespec timestruc_t;
378 -typedef struct timespec timespec_t;
381 -extern hrtime_t gethrtime(void);
382 -extern void gethrestime(timestruc_t *);
383 +typedef struct timespec timespec_t;
384 +typedef struct timespec inode_timespec_t;
387 +gethrestime(inode_timespec_t *ts)
390 + (void) gettimeofday(&tv, NULL);
391 + ts->tv_sec = tv.tv_sec;
392 + ts->tv_nsec = tv.tv_usec * NSEC_PER_USEC;
395 +static inline time_t
396 +gethrestime_sec(void)
399 + (void) gettimeofday(&tv, NULL);
400 + return (tv.tv_sec);
403 +static inline hrtime_t
406 + struct timespec ts;
407 + (void) clock_gettime(CLOCK_MONOTONIC, &ts);
408 + return ((((u_int64_t)ts.tv_sec) * NANOSEC) + ts.tv_nsec);
411 #endif /* _LIBSPL_SYS_TIME_H */
412 diff --git a/lib/libzpool/kernel.c b/lib/libzpool/kernel.c
413 index e67d13c9..3ea8778b 100644
414 --- a/lib/libzpool/kernel.c
415 +++ b/lib/libzpool/kernel.c
416 @@ -498,7 +498,7 @@ cv_timedwait(kcondvar_t *cv, kmutex_t *mp, clock_t abstime)
421 + struct timespec ts;
424 ASSERT3U(cv->cv_magic, ==, CV_MAGIC);
425 @@ -536,7 +536,7 @@ cv_timedwait_hires(kcondvar_t *cv, kmutex_t *mp, hrtime_t tim, hrtime_t res,
430 + struct timespec ts;
433 ASSERT(flag == 0 || flag == CALLOUT_FLAG_ABSOLUTE);
434 diff --git a/module/zfs/dmu_objset.c b/module/zfs/dmu_objset.c
435 index 3425d542..449ebedf 100644
436 --- a/module/zfs/dmu_objset.c
437 +++ b/module/zfs/dmu_objset.c
438 @@ -860,7 +860,7 @@ dmu_objset_evict_done(objset_t *os)
439 kmem_free(os, sizeof (objset_t));
444 dmu_objset_snap_cmtime(objset_t *os)
446 return (dsl_dir_snap_cmtime(os->os_dsl_dataset->ds_dir));
447 diff --git a/module/zfs/dsl_dir.c b/module/zfs/dsl_dir.c
448 index a3ef5896..deecf6bc 100644
449 --- a/module/zfs/dsl_dir.c
450 +++ b/module/zfs/dsl_dir.c
451 @@ -1975,10 +1975,10 @@ dsl_dir_transfer_possible(dsl_dir_t *sdd, dsl_dir_t *tdd,
457 dsl_dir_snap_cmtime(dsl_dir_t *dd)
460 + inode_timespec_t t;
462 mutex_enter(&dd->dd_lock);
463 t = dd->dd_snap_cmtime;
464 @@ -1990,7 +1990,7 @@ dsl_dir_snap_cmtime(dsl_dir_t *dd)
466 dsl_dir_snap_cmtime_update(dsl_dir_t *dd)
469 + inode_timespec_t t;
472 mutex_enter(&dd->dd_lock);
473 diff --git a/module/zfs/fm.c b/module/zfs/fm.c
474 index cb148149..9d26cc99 100644
475 --- a/module/zfs/fm.c
476 +++ b/module/zfs/fm.c
477 @@ -508,8 +508,8 @@ zfs_zevent_insert(zevent_t *ev)
479 zfs_zevent_post(nvlist_t *nvl, nvlist_t *detector, zevent_cb_t *cb)
481 + inode_timespec_t tv;
487 diff --git a/module/zfs/zfs_ctldir.c b/module/zfs/zfs_ctldir.c
488 index 14af55c4..25edea78 100644
489 --- a/module/zfs/zfs_ctldir.c
490 +++ b/module/zfs/zfs_ctldir.c
491 @@ -449,7 +449,7 @@ static struct inode *
492 zfsctl_inode_alloc(zfsvfs_t *zfsvfs, uint64_t id,
493 const struct file_operations *fops, const struct inode_operations *ops)
495 - struct timespec now;
496 + inode_timespec_t now;
500 diff --git a/module/zfs/zfs_vnops.c b/module/zfs/zfs_vnops.c
501 index 0d2b61a1..34ea751c 100644
502 --- a/module/zfs/zfs_vnops.c
503 +++ b/module/zfs/zfs_vnops.c
504 @@ -3158,7 +3158,7 @@ top:
506 if (mask & (ATTR_MTIME | ATTR_SIZE)) {
507 ZFS_TIME_ENCODE(&vap->va_mtime, mtime);
508 - ZTOI(zp)->i_mtime = timespec_trunc(vap->va_mtime,
509 + ZTOI(zp)->i_mtime = zpl_inode_timespec_trunc(vap->va_mtime,
510 ZTOI(zp)->i_sb->s_time_gran);
512 SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_MTIME(zfsvfs), NULL,
513 @@ -3167,7 +3167,7 @@ top:
515 if (mask & (ATTR_CTIME | ATTR_SIZE)) {
516 ZFS_TIME_ENCODE(&vap->va_ctime, ctime);
517 - ZTOI(zp)->i_ctime = timespec_trunc(vap->va_ctime,
518 + ZTOI(zp)->i_ctime = zpl_inode_timespec_trunc(vap->va_ctime,
519 ZTOI(zp)->i_sb->s_time_gran);
520 SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_CTIME(zfsvfs), NULL,
521 ctime, sizeof (ctime));
522 diff --git a/module/zfs/zfs_znode.c b/module/zfs/zfs_znode.c
523 index f508a248..e222c791 100644
524 --- a/module/zfs/zfs_znode.c
525 +++ b/module/zfs/zfs_znode.c
526 @@ -700,7 +700,7 @@ zfs_mknode(znode_t *dzp, vattr_t *vap, dmu_tx_t *tx, cred_t *cr,
528 zfsvfs_t *zfsvfs = ZTOZSB(dzp);
531 + inode_timespec_t now;
535 @@ -1349,7 +1349,7 @@ void
536 zfs_tstamp_update_setup(znode_t *zp, uint_t flag, uint64_t mtime[2],
540 + inode_timespec_t now;
544 diff --git a/module/zfs/zpl_inode.c b/module/zfs/zpl_inode.c
545 index 3b5643d0..41b91cab 100644
546 --- a/module/zfs/zpl_inode.c
547 +++ b/module/zfs/zpl_inode.c
548 @@ -384,9 +384,10 @@ zpl_setattr(struct dentry *dentry, struct iattr *ia)
549 vap->va_mtime = ia->ia_mtime;
550 vap->va_ctime = ia->ia_ctime;
552 - if (vap->va_mask & ATTR_ATIME)
553 - ip->i_atime = timespec_trunc(ia->ia_atime,
554 + if (vap->va_mask & ATTR_ATIME) {
555 + ip->i_atime = zpl_inode_timespec_trunc(ia->ia_atime,
556 ip->i_sb->s_time_gran);
559 cookie = spl_fstrans_mark();
560 error = -zfs_setattr(ip, vap, 0, cr);