]> git.proxmox.com Git - zfsonlinux.git/blob - 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
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
5
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.
10
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.
14
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.
19
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().
24
25 Reviewed-by: Chunwei Chen <tuxoko@gmail.com>
26 Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov>
27 Closes #7643
28 Backported-by: Richard Yao <ryao@gentoo.org>
29
30 Signed-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
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
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])
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);
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
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);
103
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 */
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);
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
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;
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 */
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
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 {
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
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)
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 */
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
253
254 USER_C = \
255 getexecname.c \
256 - gethrtime.c \
257 - gethrestime.c \
258 getmntany.c \
259 list.c \
260 mkdirp.c \
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
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 -}
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
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 -}
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
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 */
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)
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);
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));
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));
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,
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);
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)
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;
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)
494 {
495 - struct timespec now;
496 + inode_timespec_t now;
497 struct inode *ip;
498 znode_t *zp;
499
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:
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));
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,
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
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;
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);