Skip to content

Commit c5b29f8

Browse files
neilbrownJ. Bruce Fields
authored and
J. Bruce Fields
committed
sunrpc: use seconds since boot in expiry cache
This protects us from confusion when the wallclock time changes. We convert to and from wallclock when setting or reading expiry times. Also use seconds since boot for last_clost time. Signed-off-by: NeilBrown <[email protected]> Signed-off-by: J. Bruce Fields <[email protected]>
1 parent 17cebf6 commit c5b29f8

File tree

4 files changed

+48
-24
lines changed

4 files changed

+48
-24
lines changed

fs/nfs/dns_resolve.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,7 @@ static int nfs_dns_show(struct seq_file *m, struct cache_detail *cd,
167167
return 0;
168168
}
169169
item = container_of(h, struct nfs_dns_ent, h);
170-
ttl = (long)item->h.expiry_time - (long)get_seconds();
170+
ttl = item->h.expiry_time - seconds_since_boot();
171171
if (ttl < 0)
172172
ttl = 0;
173173

@@ -239,7 +239,7 @@ static int nfs_dns_parse(struct cache_detail *cd, char *buf, int buflen)
239239
ttl = get_expiry(&buf);
240240
if (ttl == 0)
241241
goto out;
242-
key.h.expiry_time = ttl + get_seconds();
242+
key.h.expiry_time = ttl + seconds_since_boot();
243243

244244
ret = -ENOMEM;
245245
item = nfs_dns_lookup(cd, &key);
@@ -301,7 +301,7 @@ static int do_cache_lookup_nowait(struct cache_detail *cd,
301301
goto out_err;
302302
ret = -ETIMEDOUT;
303303
if (!test_bit(CACHE_VALID, &(*item)->h.flags)
304-
|| (*item)->h.expiry_time < get_seconds()
304+
|| (*item)->h.expiry_time < seconds_since_boot()
305305
|| cd->flush_time > (*item)->h.last_refresh)
306306
goto out_put;
307307
ret = -ENOENT;

fs/nfsd/nfs4idmap.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -550,7 +550,7 @@ do_idmap_lookup_nowait(struct ent *(*lookup_fn)(struct ent *),
550550
goto out_err;
551551
ret = -ETIMEDOUT;
552552
if (!test_bit(CACHE_VALID, &(*item)->h.flags)
553-
|| (*item)->h.expiry_time < get_seconds()
553+
|| (*item)->h.expiry_time < seconds_since_boot()
554554
|| detail->flush_time > (*item)->h.last_refresh)
555555
goto out_put;
556556
ret = -ENOENT;

include/linux/sunrpc/cache.h

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -218,20 +218,42 @@ static inline int get_int(char **bpp, int *anint)
218218
return 0;
219219
}
220220

221+
/*
222+
* timestamps kept in the cache are expressed in seconds
223+
* since boot. This is the best for measuring differences in
224+
* real time.
225+
*/
226+
static inline time_t seconds_since_boot(void)
227+
{
228+
struct timespec boot;
229+
getboottime(&boot);
230+
return get_seconds() - boot.tv_sec;
231+
}
232+
233+
static inline time_t convert_to_wallclock(time_t sinceboot)
234+
{
235+
struct timespec boot;
236+
getboottime(&boot);
237+
return boot.tv_sec + sinceboot;
238+
}
239+
221240
static inline time_t get_expiry(char **bpp)
222241
{
223242
int rv;
243+
struct timespec boot;
244+
224245
if (get_int(bpp, &rv))
225246
return 0;
226247
if (rv < 0)
227248
return 0;
228-
return rv;
249+
getboottime(&boot);
250+
return rv - boot.tv_sec;
229251
}
230252

231253
static inline void sunrpc_invalidate(struct cache_head *h,
232254
struct cache_detail *detail)
233255
{
234-
h->expiry_time = get_seconds() - 1;
235-
detail->nextcheck = get_seconds();
256+
h->expiry_time = seconds_since_boot() - 1;
257+
detail->nextcheck = seconds_since_boot();
236258
}
237259
#endif /* _LINUX_SUNRPC_CACHE_H_ */

net/sunrpc/cache.c

Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ static void cache_revisit_request(struct cache_head *item);
4242

4343
static void cache_init(struct cache_head *h)
4444
{
45-
time_t now = get_seconds();
45+
time_t now = seconds_since_boot();
4646
h->next = NULL;
4747
h->flags = 0;
4848
kref_init(&h->ref);
@@ -52,7 +52,7 @@ static void cache_init(struct cache_head *h)
5252

5353
static inline int cache_is_expired(struct cache_detail *detail, struct cache_head *h)
5454
{
55-
return (h->expiry_time < get_seconds()) ||
55+
return (h->expiry_time < seconds_since_boot()) ||
5656
(detail->flush_time > h->last_refresh);
5757
}
5858

@@ -127,7 +127,7 @@ static void cache_dequeue(struct cache_detail *detail, struct cache_head *ch);
127127
static void cache_fresh_locked(struct cache_head *head, time_t expiry)
128128
{
129129
head->expiry_time = expiry;
130-
head->last_refresh = get_seconds();
130+
head->last_refresh = seconds_since_boot();
131131
set_bit(CACHE_VALID, &head->flags);
132132
}
133133

@@ -238,7 +238,7 @@ int cache_check(struct cache_detail *detail,
238238

239239
/* now see if we want to start an upcall */
240240
refresh_age = (h->expiry_time - h->last_refresh);
241-
age = get_seconds() - h->last_refresh;
241+
age = seconds_since_boot() - h->last_refresh;
242242

243243
if (rqstp == NULL) {
244244
if (rv == -EAGAIN)
@@ -253,7 +253,7 @@ int cache_check(struct cache_detail *detail,
253253
cache_revisit_request(h);
254254
if (rv == -EAGAIN) {
255255
set_bit(CACHE_NEGATIVE, &h->flags);
256-
cache_fresh_locked(h, get_seconds()+CACHE_NEW_EXPIRY);
256+
cache_fresh_locked(h, seconds_since_boot()+CACHE_NEW_EXPIRY);
257257
cache_fresh_unlocked(h, detail);
258258
rv = -ENOENT;
259259
}
@@ -388,11 +388,11 @@ static int cache_clean(void)
388388
return -1;
389389
}
390390
current_detail = list_entry(next, struct cache_detail, others);
391-
if (current_detail->nextcheck > get_seconds())
391+
if (current_detail->nextcheck > seconds_since_boot())
392392
current_index = current_detail->hash_size;
393393
else {
394394
current_index = 0;
395-
current_detail->nextcheck = get_seconds()+30*60;
395+
current_detail->nextcheck = seconds_since_boot()+30*60;
396396
}
397397
}
398398

@@ -477,7 +477,7 @@ EXPORT_SYMBOL_GPL(cache_flush);
477477
void cache_purge(struct cache_detail *detail)
478478
{
479479
detail->flush_time = LONG_MAX;
480-
detail->nextcheck = get_seconds();
480+
detail->nextcheck = seconds_since_boot();
481481
cache_flush();
482482
detail->flush_time = 1;
483483
}
@@ -902,7 +902,7 @@ static int cache_release(struct inode *inode, struct file *filp,
902902
filp->private_data = NULL;
903903
kfree(rp);
904904

905-
cd->last_close = get_seconds();
905+
cd->last_close = seconds_since_boot();
906906
atomic_dec(&cd->readers);
907907
}
908908
module_put(cd->owner);
@@ -1034,7 +1034,7 @@ int sunrpc_cache_pipe_upcall(struct cache_detail *detail, struct cache_head *h,
10341034
int len;
10351035

10361036
if (atomic_read(&detail->readers) == 0 &&
1037-
detail->last_close < get_seconds() - 30) {
1037+
detail->last_close < seconds_since_boot() - 30) {
10381038
warn_no_listener(detail);
10391039
return -EINVAL;
10401040
}
@@ -1219,7 +1219,8 @@ static int c_show(struct seq_file *m, void *p)
12191219

12201220
ifdebug(CACHE)
12211221
seq_printf(m, "# expiry=%ld refcnt=%d flags=%lx\n",
1222-
cp->expiry_time, atomic_read(&cp->ref.refcount), cp->flags);
1222+
convert_to_wallclock(cp->expiry_time),
1223+
atomic_read(&cp->ref.refcount), cp->flags);
12231224
cache_get(cp);
12241225
if (cache_check(cd, cp, NULL))
12251226
/* cache_check does a cache_put on failure */
@@ -1285,7 +1286,7 @@ static ssize_t read_flush(struct file *file, char __user *buf,
12851286
unsigned long p = *ppos;
12861287
size_t len;
12871288

1288-
sprintf(tbuf, "%lu\n", cd->flush_time);
1289+
sprintf(tbuf, "%lu\n", convert_to_wallclock(cd->flush_time));
12891290
len = strlen(tbuf);
12901291
if (p >= len)
12911292
return 0;
@@ -1303,19 +1304,20 @@ static ssize_t write_flush(struct file *file, const char __user *buf,
13031304
struct cache_detail *cd)
13041305
{
13051306
char tbuf[20];
1306-
char *ep;
1307-
long flushtime;
1307+
char *bp, *ep;
1308+
13081309
if (*ppos || count > sizeof(tbuf)-1)
13091310
return -EINVAL;
13101311
if (copy_from_user(tbuf, buf, count))
13111312
return -EFAULT;
13121313
tbuf[count] = 0;
1313-
flushtime = simple_strtoul(tbuf, &ep, 0);
1314+
simple_strtoul(tbuf, &ep, 0);
13141315
if (*ep && *ep != '\n')
13151316
return -EINVAL;
13161317

1317-
cd->flush_time = flushtime;
1318-
cd->nextcheck = get_seconds();
1318+
bp = tbuf;
1319+
cd->flush_time = get_expiry(&bp);
1320+
cd->nextcheck = seconds_since_boot();
13191321
cache_flush();
13201322

13211323
*ppos += count;

0 commit comments

Comments
 (0)