Here, we actually have a problem in 2038 or at the latest in 2106 when the lc_expiry variable on the wire protocol overflows, including on 64-bit architectures.
I'm changing the internal implementation so it only compares the lower 31 bits of the current time, using the algorithm from time_before(), which should work as long as nothing tries to directly access lc_expiry.
Signed-off-by: Arnd Bergmann arnd@arndb.de --- .../staging/lustre/lustre/include/lustre/lustre_idl.h | 1 + drivers/staging/lustre/lustre/include/lustre_capa.h | 16 ++++++++++------ 2 files changed, 11 insertions(+), 6 deletions(-)
diff --git a/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h b/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h index d20e199eb770..e0cec23e8344 100644 --- a/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h +++ b/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h @@ -3478,6 +3478,7 @@ struct lustre_capa { __u32 lc_flags; /** HMAC algorithm & flags */ __u32 lc_keyid; /** key# used for the capability */ __u32 lc_timeout; /** capa timeout value (sec) */ +/* FIXME: y2038 time_t overflow: */ __u32 lc_expiry; /** expiry time (sec) */ __u8 lc_hmac[CAPA_HMAC_MAX_LEN]; /** HMAC */ } __attribute__((packed)); diff --git a/drivers/staging/lustre/lustre/include/lustre_capa.h b/drivers/staging/lustre/lustre/include/lustre_capa.h index 11bcdb935443..b75f7308d777 100644 --- a/drivers/staging/lustre/lustre/include/lustre_capa.h +++ b/drivers/staging/lustre/lustre/include/lustre_capa.h @@ -266,20 +266,24 @@ static inline __u64 capa_open_opc(int mode)
static inline void set_capa_expiry(struct obd_capa *ocapa) { - unsigned long expiry = cfs_time_sub((unsigned long)ocapa->c_capa.lc_expiry, - get_seconds()); - ocapa->c_expiry = cfs_time_add(cfs_time_current(), - cfs_time_seconds(expiry)); + u32 expiry = ocapa->c_capa.lc_expiry - (u32)ktime_get_real_seconds(); + ocapa->c_expiry = jiffies + expiry * HZ; }
static inline int capa_is_expired_sec(struct lustre_capa *capa) { - return (capa->lc_expiry - get_seconds() <= 0); + /* + * workaround for y2038 problem: do the same as time_before, but + * use 32-bit arithmetic, because lc_expiry is transmitted as a 32-bit + * variable on the wire + */ + s32 diff = capa->lc_expiry - (u32)ktime_get_real_seconds(); + return diff <= 0; }
static inline int capa_is_expired(struct obd_capa *ocapa) { - return time_before_eq(ocapa->c_expiry, cfs_time_current()); + return time_before_eq(ocapa->c_expiry, jiffies); }
static inline int capa_opc_supported(struct lustre_capa *capa, __u64 opc)