nfsd: make 'boot_time' 64-bit wide
authorArnd Bergmann <arnd@arndb.de>
Thu, 31 Oct 2019 14:53:13 +0000 (15:53 +0100)
committerJ. Bruce Fields <bfields@redhat.com>
Thu, 19 Dec 2019 22:46:08 +0000 (17:46 -0500)
The local boot time variable gets truncated to time_t at the moment,
which can lead to slightly odd behavior on 32-bit architectures.

Use ktime_get_real_seconds() instead of get_seconds() to always
get a 64-bit result, and keep it that way wherever possible.

It still gets truncated in a few places:

- When assigning to cl_clientid.cl_boot, this is already documented
  and is only used as a unique identifier.

- In clients_still_reclaiming(), the truncation is to 'unsigned long'
  in order to use the 'time_before() helper.

Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
fs/nfsd/netns.h
fs/nfsd/nfs4recover.c
fs/nfsd/nfs4state.c

index 9a4ef815fb8c1a29cc5ba046b3ce170707aefd11..29bbe28eda5350312362cdd3412676a1ea7f8aa6 100644 (file)
@@ -40,7 +40,7 @@ struct nfsd_net {
 
        struct lock_manager nfsd4_manager;
        bool grace_ended;
-       time_t boot_time;
+       time64_t boot_time;
 
        /* internal mount of the "nfsd" pseudofilesystem: */
        struct vfsmount *nfsd_mnt;
index 2481e7662128f235f4bd9d307ea4b2769bab298d..a8fb18609146a2a07cd63d652e98770431ba76e6 100644 (file)
@@ -1445,7 +1445,7 @@ nfsd4_cld_grace_done_v0(struct nfsd_net *nn)
        }
 
        cup->cu_u.cu_msg.cm_cmd = Cld_GraceDone;
-       cup->cu_u.cu_msg.cm_u.cm_gracetime = (int64_t)nn->boot_time;
+       cup->cu_u.cu_msg.cm_u.cm_gracetime = nn->boot_time;
        ret = cld_pipe_upcall(cn->cn_pipe, &cup->cu_u.cu_msg);
        if (!ret)
                ret = cup->cu_u.cu_msg.cm_status;
@@ -1782,7 +1782,7 @@ nfsd4_cltrack_client_has_session(struct nfs4_client *clp)
 }
 
 static char *
-nfsd4_cltrack_grace_start(time_t grace_start)
+nfsd4_cltrack_grace_start(time64_t grace_start)
 {
        int copied;
        size_t len;
@@ -1795,7 +1795,7 @@ nfsd4_cltrack_grace_start(time_t grace_start)
        if (!result)
                return result;
 
-       copied = snprintf(result, len, GRACE_START_ENV_PREFIX "%ld",
+       copied = snprintf(result, len, GRACE_START_ENV_PREFIX "%lld",
                                grace_start);
        if (copied >= len) {
                /* just return nothing if output was truncated */
@@ -2004,7 +2004,7 @@ nfsd4_umh_cltrack_grace_done(struct nfsd_net *nn)
        char *legacy;
        char timestr[22]; /* FIXME: better way to determine max size? */
 
-       sprintf(timestr, "%ld", nn->boot_time);
+       sprintf(timestr, "%lld", nn->boot_time);
        legacy = nfsd4_cltrack_legacy_topdir();
        nfsd4_umh_cltrack_upcall("gracedone", timestr, legacy, NULL);
        kfree(legacy);
index 27e1c12618b8b22a94d78a3f6356ed875a3761e6..a178374bacd5d521984b96024782737f036dcc9a 100644 (file)
@@ -748,7 +748,7 @@ static int nfs4_init_cp_state(struct nfsd_net *nn, copy_stateid_t *stid,
 {
        int new_id;
 
-       stid->stid.si_opaque.so_clid.cl_boot = nn->boot_time;
+       stid->stid.si_opaque.so_clid.cl_boot = (u32)nn->boot_time;
        stid->stid.si_opaque.so_clid.cl_id = nn->s2s_cp_cl_id;
        stid->sc_type = sc_type;
 
@@ -1911,7 +1911,7 @@ STALE_CLIENTID(clientid_t *clid, struct nfsd_net *nn)
         */
        if (clid->cl_boot == (u32)nn->boot_time)
                return 0;
-       dprintk("NFSD stale clientid (%08x/%08x) boot_time %08lx\n",
+       dprintk("NFSD stale clientid (%08x/%08x) boot_time %08llx\n",
                clid->cl_boot, clid->cl_id, nn->boot_time);
        return 1;
 }
@@ -2271,7 +2271,7 @@ static void gen_confirm(struct nfs4_client *clp, struct nfsd_net *nn)
 
 static void gen_clid(struct nfs4_client *clp, struct nfsd_net *nn)
 {
-       clp->cl_clientid.cl_boot = nn->boot_time;
+       clp->cl_clientid.cl_boot = (u32)nn->boot_time;
        clp->cl_clientid.cl_id = nn->clientid_counter++;
        gen_confirm(clp, nn);
 }
@@ -5233,9 +5233,9 @@ nfsd4_end_grace(struct nfsd_net *nn)
  */
 static bool clients_still_reclaiming(struct nfsd_net *nn)
 {
-       unsigned long now = get_seconds();
-       unsigned long double_grace_period_end = nn->boot_time +
-                                               2 * nn->nfsd4_lease;
+       unsigned long now = (unsigned long) ktime_get_real_seconds();
+       unsigned long double_grace_period_end = (unsigned long)nn->boot_time +
+                                          2 * (unsigned long)nn->nfsd4_lease;
 
        if (nn->track_reclaim_completes &&
                        atomic_read(&nn->nr_reclaim_complete) ==
@@ -7792,7 +7792,7 @@ static int nfs4_state_create_net(struct net *net)
                INIT_LIST_HEAD(&nn->sessionid_hashtbl[i]);
        nn->conf_name_tree = RB_ROOT;
        nn->unconf_name_tree = RB_ROOT;
-       nn->boot_time = get_seconds();
+       nn->boot_time = ktime_get_real_seconds();
        nn->grace_ended = false;
        nn->nfsd4_manager.block_opens = true;
        INIT_LIST_HEAD(&nn->nfsd4_manager.list);