]> git.proxmox.com Git - zfsonlinux.git/blame - zfs-patches/0006-Linux-4.18-compat-inode-timespec-timespec64.patch
update/rebase to zfs-0.7.10 with patches from ZOL
[zfsonlinux.git] / zfs-patches / 0006-Linux-4.18-compat-inode-timespec-timespec64.patch
CommitLineData
a010b409
SI
1From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
2From: Brian Behlendorf <behlendorf1@llnl.gov>
3Date: Sun, 12 Aug 2018 18:22:03 -0400
4Subject: [PATCH] Linux 4.18 compat: inode timespec -> timespec64
5
6Commit torvalds/linux@95582b0 changes the inode i_atime, i_mtime,
7and i_ctime members form timespec's to timespec64's to make them
82038 safe. As part of this change the current_time() function was
9also updated to return the timespec64 type.
10
11Resolve this issue by introducing a new inode_timespec_t type which
12is defined to match the timespec type used by the inode. It should
13be used when working with inode timestamps to ensure matching types.
14
15The timestruc_t type under Illumos was used in a similar fashion but
16was specified to always be a timespec_t. Rather than incorrectly
17define this type all timespec_t types have been replaced by the new
18inode_timespec_t type.
19
20Finally, the kernel and user space 'sys/time.h' headers were aligned
21with each other. They define as appropriate for the context several
22constants as macros and include static inline implementation of
23gethrestime(), gethrestime_sec(), and gethrtime().
24
25Reviewed-by: Chunwei Chen <tuxoko@gmail.com>
26Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov>
27Closes #7643
28Backported-by: Richard Yao <ryao@gentoo.org>
29
30Signed-off-by: Stoiko Ivanov <s.ivanov@proxmox.com>
31---
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
56
57diff --git a/config/kernel-current-time.m4 b/config/kernel-current-time.m4
58index 2ede9ff3..c7d5c9b5 100644
59--- a/config/kernel-current-time.m4
60+++ b/config/kernel-current-time.m4
61@@ -1,15 +1,14 @@
62 dnl #
63 dnl # 4.9, current_time() added
64+dnl # 4.18, return type changed from timespec to timespec64
65 dnl #
66 AC_DEFUN([ZFS_AC_KERNEL_CURRENT_TIME],
67 [AC_MSG_CHECKING([whether current_time() exists])
68 ZFS_LINUX_TRY_COMPILE_SYMBOL([
69 #include <linux/fs.h>
70 ], [
71- struct inode ip;
72- struct timespec now __attribute__ ((unused));
73-
74- now = current_time(&ip);
75+ struct inode ip __attribute__ ((unused));
76+ ip.i_atime = current_time(&ip);
77 ], [current_time], [fs/inode.c], [
78 AC_MSG_RESULT(yes)
79 AC_DEFINE(HAVE_CURRENT_TIME, 1, [current_time() exists])
80diff --git a/include/sys/dmu.h b/include/sys/dmu.h
81index 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);
85 /*
86 * Get the [cm]time for an objset's snapshot dir
87 */
88-timestruc_t dmu_objset_snap_cmtime(objset_t *os);
89+inode_timespec_t dmu_objset_snap_cmtime(objset_t *os);
90
91 int dmu_objset_is_snapshot(objset_t *os);
92
93diff --git a/include/sys/dmu_objset.h b/include/sys/dmu_objset.h
94index 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);
103
104 /* called from dsl */
105 void dmu_objset_sync(objset_t *os, zio_t *zio, dmu_tx_t *tx);
106diff --git a/include/sys/dsl_dir.h b/include/sys/dsl_dir.h
107index 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 */
112 kmutex_t 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;
117
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,
126 dmu_tx_t *tx);
127 void dsl_dir_zapify(dsl_dir_t *dd, dmu_tx_t *tx);
128diff --git a/include/sys/spa_impl.h b/include/sys/spa_impl.h
129index 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. */
141diff --git a/include/sys/xvattr.h b/include/sys/xvattr.h
142index 4779b632..5d38927c 100644
143--- a/include/sys/xvattr.h
144+++ b/include/sys/xvattr.h
145@@ -47,7 +47,7 @@
146 * Structure of all optional attributes.
147 */
148 typedef struct xoptattr {
149- timestruc_t xoa_createtime; /* Create time of file */
150+ inode_timespec_t xoa_createtime; /* Create time of file */
151 uint8_t xoa_archive;
152 uint8_t xoa_system;
153 uint8_t xoa_readonly;
154diff --git a/include/sys/zfs_context.h b/include/sys/zfs_context.h
155index 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 */
160
161 typedef struct xoptattr {
162- timestruc_t xoa_createtime; /* Create time of file */
163+ inode_timespec_t xoa_createtime; /* Create time of file */
164 uint8_t xoa_archive;
165 uint8_t xoa_system;
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))
170
171-#define gethrestime_sec() time(NULL)
172-#define gethrestime(t) \
173- do {\
174- (t)->tv_sec = gethrestime_sec();\
175- (t)->tv_nsec = 0;\
176- } while (0);
177-
178 #define max_ncpus 64
179 #define boot_ncpus (sysconf(_SC_NPROCESSORS_ONLN))
180
181diff --git a/include/sys/zfs_znode.h b/include/sys/zfs_znode.h
182index 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 {
186
187 extern unsigned int zfs_object_mutex_size;
188
189-/* Encode ZFS stored time values from a struct timespec */
190+/*
191+ * Encode ZFS stored time values from a struct timespec / struct timespec64.
192+ */
193 #define ZFS_TIME_ENCODE(tp, stmp) \
194-{ \
195+do { \
196 (stmp)[0] = (uint64_t)(tp)->tv_sec; \
197 (stmp)[1] = (uint64_t)(tp)->tv_nsec; \
198-}
199+} while (0)
200
201-/* Decode ZFS stored time values to a struct timespec */
202+#if defined(HAVE_INODE_TIMESPEC64_TIMES)
203+/*
204+ * Decode ZFS stored time values to a struct timespec64
205+ * 4.18 and newer kernels.
206+ */
207 #define ZFS_TIME_DECODE(tp, stmp) \
208-{ \
209- (tp)->tv_sec = (time_t)(stmp)[0]; \
210- (tp)->tv_nsec = (long)(stmp)[1]; \
211-}
212+do { \
213+ (tp)->tv_sec = (time64_t)(stmp)[0]; \
214+ (tp)->tv_nsec = (long)(stmp)[1]; \
215+} while (0)
216+#else
217+/*
218+ * Decode ZFS stored time values to a struct timespec
219+ * 4.17 and older kernels.
220+ */
221+#define ZFS_TIME_DECODE(tp, stmp) \
222+do { \
223+ (tp)->tv_sec = (time_t)(stmp)[0]; \
224+ (tp)->tv_nsec = (long)(stmp)[1]; \
225+} while (0)
226+#endif /* HAVE_INODE_TIMESPEC64_TIMES */
227
228 /*
229 * Timestamp defines
230diff --git a/include/sys/zpl.h b/include/sys/zpl.h
231index 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)
235 }
236 #endif /* HAVE_VFS_ITERATE */
237
238+/*
239+ * Linux 4.18, inode times converted from timespec to timespec64.
240+ */
241+#if defined(HAVE_INODE_TIMESPEC64_TIMES)
242+#define zpl_inode_timespec_trunc(ts, gran) timespec64_trunc(ts, gran)
243+#else
244+#define zpl_inode_timespec_trunc(ts, gran) timespec_trunc(ts, gran)
245+#endif
246+
247 #endif /* _SYS_ZPL_H */
248diff --git a/lib/libspl/Makefile.am b/lib/libspl/Makefile.am
249index 59bc8ffb..a6e63cb8 100644
250--- a/lib/libspl/Makefile.am
251+++ b/lib/libspl/Makefile.am
252@@ -19,8 +19,6 @@ noinst_LTLIBRARIES = libspl.la
253
254 USER_C = \
255 getexecname.c \
256- gethrtime.c \
257- gethrestime.c \
258 getmntany.c \
259 list.c \
260 mkdirp.c \
261diff --git a/lib/libspl/gethrestime.c b/lib/libspl/gethrestime.c
262deleted file mode 100644
263index d37cc2d5..00000000
264--- a/lib/libspl/gethrestime.c
265+++ /dev/null
266@@ -1,38 +0,0 @@
267-/*
268- * CDDL HEADER START
269- *
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.
273- *
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.
278- *
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]
284- *
285- * CDDL HEADER END
286- */
287-
288-/*
289- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
290- * Use is subject to license terms.
291- */
292-
293-#include <time.h>
294-#include <sys/time.h>
295-
296-void
297-gethrestime(timestruc_t *ts)
298-{
299- struct timeval tv;
300-
301- gettimeofday(&tv, NULL);
302- ts->tv_sec = tv.tv_sec;
303- ts->tv_nsec = tv.tv_usec * NSEC_PER_USEC;
304-}
305diff --git a/lib/libspl/gethrtime.c b/lib/libspl/gethrtime.c
306deleted file mode 100644
307index 95ceb18e..00000000
308--- a/lib/libspl/gethrtime.c
309+++ /dev/null
310@@ -1,45 +0,0 @@
311-/*
312- * CDDL HEADER START
313- *
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.
317- *
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.
322- *
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]
328- *
329- * CDDL HEADER END
330- */
331-
332-/*
333- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
334- * Use is subject to license terms.
335- */
336-
337-#include <time.h>
338-#include <sys/time.h>
339-#include <stdlib.h>
340-#include <stdio.h>
341-
342-hrtime_t
343-gethrtime(void)
344-{
345- struct timespec ts;
346- int rc;
347-
348- rc = clock_gettime(CLOCK_MONOTONIC, &ts);
349- if (rc) {
350- fprintf(stderr, "Error: clock_gettime() = %d\n", rc);
351- abort();
352- }
353-
354- return ((((u_int64_t)ts.tv_sec) * NANOSEC) + ts.tv_nsec);
355-}
356diff --git a/lib/libspl/include/sys/time.h b/lib/libspl/include/sys/time.h
357index dc645fa5..04b3ba87 100644
358--- a/lib/libspl/include/sys/time.h
359+++ b/lib/libspl/include/sys/time.h
360@@ -27,8 +27,9 @@
361 #ifndef _LIBSPL_SYS_TIME_H
362 #define _LIBSPL_SYS_TIME_H
363
364-#include_next <sys/time.h>
365+#include <time.h>
366 #include <sys/types.h>
367+#include_next <sys/time.h>
368
369 #ifndef SEC
370 #define SEC 1
371@@ -70,13 +71,33 @@
372 #define SEC2NSEC(m) ((hrtime_t)(m) * (NANOSEC / SEC))
373 #endif
374
375-
376 typedef long long hrtime_t;
377-typedef struct timespec timestruc_t;
378-typedef struct timespec timespec_t;
379-
380-
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;
385+
386+static inline void
387+gethrestime(inode_timespec_t *ts)
388+{
389+ struct timeval tv;
390+ (void) gettimeofday(&tv, NULL);
391+ ts->tv_sec = tv.tv_sec;
392+ ts->tv_nsec = tv.tv_usec * NSEC_PER_USEC;
393+}
394+
395+static inline time_t
396+gethrestime_sec(void)
397+{
398+ struct timeval tv;
399+ (void) gettimeofday(&tv, NULL);
400+ return (tv.tv_sec);
401+}
402+
403+static inline hrtime_t
404+gethrtime(void)
405+{
406+ struct timespec ts;
407+ (void) clock_gettime(CLOCK_MONOTONIC, &ts);
408+ return ((((u_int64_t)ts.tv_sec) * NANOSEC) + ts.tv_nsec);
409+}
410
411 #endif /* _LIBSPL_SYS_TIME_H */
412diff --git a/lib/libzpool/kernel.c b/lib/libzpool/kernel.c
413index 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)
417 {
418 int error;
419 struct timeval tv;
420- timestruc_t ts;
421+ struct timespec ts;
422 clock_t delta;
423
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,
426 {
427 int error;
428 struct timeval tv;
429- timestruc_t ts;
430+ struct timespec ts;
431 hrtime_t delta;
432
433 ASSERT(flag == 0 || flag == CALLOUT_FLAG_ABSOLUTE);
434diff --git a/module/zfs/dmu_objset.c b/module/zfs/dmu_objset.c
435index 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));
440 }
441
442-timestruc_t
443+inode_timespec_t
444 dmu_objset_snap_cmtime(objset_t *os)
445 {
446 return (dsl_dir_snap_cmtime(os->os_dsl_dataset->ds_dir));
447diff --git a/module/zfs/dsl_dir.c b/module/zfs/dsl_dir.c
448index 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,
452 return (0);
453 }
454
455-timestruc_t
456+inode_timespec_t
457 dsl_dir_snap_cmtime(dsl_dir_t *dd)
458 {
459- timestruc_t t;
460+ inode_timespec_t t;
461
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)
465 void
466 dsl_dir_snap_cmtime_update(dsl_dir_t *dd)
467 {
468- timestruc_t t;
469+ inode_timespec_t t;
470
471 gethrestime(&t);
472 mutex_enter(&dd->dd_lock);
473diff --git a/module/zfs/fm.c b/module/zfs/fm.c
474index 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)
478 int
479 zfs_zevent_post(nvlist_t *nvl, nvlist_t *detector, zevent_cb_t *cb)
480 {
481+ inode_timespec_t tv;
482 int64_t tv_array[2];
483- timestruc_t tv;
484 uint64_t eid;
485 size_t nvl_size = 0;
486 zevent_t *ev;
487diff --git a/module/zfs/zfs_ctldir.c b/module/zfs/zfs_ctldir.c
488index 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)
494 {
495- struct timespec now;
496+ inode_timespec_t now;
497 struct inode *ip;
498 znode_t *zp;
499
500diff --git a/module/zfs/zfs_vnops.c b/module/zfs/zfs_vnops.c
501index 0d2b61a1..34ea751c 100644
502--- a/module/zfs/zfs_vnops.c
503+++ b/module/zfs/zfs_vnops.c
504@@ -3158,7 +3158,7 @@ top:
505
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);
511
512 SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_MTIME(zfsvfs), NULL,
513@@ -3167,7 +3167,7 @@ top:
514
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));
522diff --git a/module/zfs/zfs_znode.c b/module/zfs/zfs_znode.c
523index 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,
527 uint64_t rdev = 0;
528 zfsvfs_t *zfsvfs = ZTOZSB(dzp);
529 dmu_buf_t *db;
530- timestruc_t now;
531+ inode_timespec_t now;
532 uint64_t gen, obj;
533 int bonuslen;
534 int dnodesize;
535@@ -1349,7 +1349,7 @@ void
536 zfs_tstamp_update_setup(znode_t *zp, uint_t flag, uint64_t mtime[2],
537 uint64_t ctime[2])
538 {
539- timestruc_t now;
540+ inode_timespec_t now;
541
542 gethrestime(&now);
543
544diff --git a/module/zfs/zpl_inode.c b/module/zfs/zpl_inode.c
545index 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;
551
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);
557+ }
558
559 cookie = spl_fstrans_mark();
560 error = -zfs_setattr(ip, vap, 0, cr);