1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105
|
/*
* cnoconv.c - checkpoint number converter (time to checkpoint number)
*
* Licensed under LGPLv2: the complete text of the GNU Lesser General
* Public License can be found in COPYING file of the nilfs-utils
* package.
*
* Copyright (C) 2008-2012 Nippon Telegraph and Telephone Corporation.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif /* HAVE_CONFIG_H */
#include <stdio.h>
#if HAVE_STDLIB_H
#include <stdlib.h>
#endif /* HAVE_STDLIB_H */
#include "util.h"
#include "cnoconv.h"
/* Context of checkpoint number/time converter */
struct nilfs_cnoconv {
struct nilfs *nilfs;
nilfs_cno_t prevcno; /* start number of protected checkpoint */
__u64 prevtime; /* start time of protection */
};
void nilfs_cnoconv_reset(struct nilfs_cnoconv *cnoconv)
{
cnoconv->prevcno = 0;
cnoconv->prevtime = 0;
}
struct nilfs_cnoconv *nilfs_cnoconv_create(struct nilfs *nilfs)
{
struct nilfs_cnoconv *cnoconv;
cnoconv = malloc(sizeof(*cnoconv));
if (cnoconv) {
cnoconv->nilfs = nilfs;
nilfs_cnoconv_reset(cnoconv);
}
return cnoconv;
}
void nilfs_cnoconv_destroy(struct nilfs_cnoconv *cnoconv)
{
free(cnoconv);
}
#define NILFS_CNOCONV_NCPINFO 512
/**
* nilfs_conconv_time2cno - reverse map time to checkpoint number
* @nilfs: nilfs object
* @time: time to be converted
* @cnop: buffer to store resultant checkpoint number
*/
int nilfs_cnoconv_time2cno(struct nilfs_cnoconv *cnoconv, __u64 time,
nilfs_cno_t *cnop)
{
struct nilfs_cpstat cpstat;
struct nilfs_cpinfo cpinfo[NILFS_CNOCONV_NCPINFO];
nilfs_cno_t cno;
size_t count;
ssize_t n;
int i;
if (nilfs_get_cpstat(cnoconv->nilfs, &cpstat) < 0)
return -1;
if (cnoconv->prevtime > time)
cnoconv->prevcno = 0;
else if (cnoconv->prevtime == time)
goto out_unchanged; /* time unchanged */
cno = (cnoconv->prevcno == 0) ? NILFS_CNO_MIN : cnoconv->prevcno;
while (cno < cpstat.cs_cno) {
count = min_t(nilfs_cno_t, cpstat.cs_cno - cno,
NILFS_CNOCONV_NCPINFO);
n = nilfs_get_cpinfo(cnoconv->nilfs, cno, NILFS_CHECKPOINT,
cpinfo, count);
if (n < 0)
return -1;
if (n == 0)
break;
for (i = 0; i < n; i++) {
if (cpinfo[i].ci_create >= time) {
cnoconv->prevcno = cpinfo[i].ci_cno;
goto out;
}
}
cno = cpinfo[n - 1].ci_cno + 1;
}
cnoconv->prevcno = cno;
out:
cnoconv->prevtime = time;
out_unchanged:
*cnop = cnoconv->prevcno;
return 0;
}
|