From: NeilBrown Date: Fri, 4 Mar 2011 23:44:22 +0000 (+1100) Subject: accesstime: load delta from atime file and apply when loading inode. X-Git-Url: http://git.neil.brown.name/?a=commitdiff_plain;h=1eb2efdfa4a54f3f39df0cbaec135c07bdc8fc5e;p=LaFS.git accesstime: load delta from atime file and apply when loading inode. Signed-off-by: NeilBrown --- diff --git a/inode.c b/inode.c index fd8ab77..681b8fe 100644 --- a/inode.c +++ b/inode.c @@ -14,6 +14,8 @@ #include #include +static void check_atime_ref(struct inode *ino, int async); + /* Supporting an async 'iget' - as required by the cleaner - * is slightly non-trivial. * iget*_locked will normally wait for any inode with one @@ -139,8 +141,10 @@ lafs_iget(struct super_block *sb, ino_t inum, int async) if (!(ino->i_state & I_NEW)) { putdref(b, MKREF(iget)); - if (ino->i_mode) + if (ino->i_mode) { + check_atime_ref(ino, async); return ino; + } iput(ino); return ERR_PTR(-ENOENT); } @@ -185,6 +189,7 @@ lafs_iget(struct super_block *sb, ino_t inum, int async) printk("lafs_import_inode failed %d\n", err); goto err; } + check_atime_ref(ino, async); unlock_new_inode(ino); out: if (b && test_and_clear_bit(B_Async, &b->b.flags)) { @@ -389,8 +394,9 @@ lafs_import_inode(struct inode *ino, struct datablock *b) decode_time(&ino->i_mtime, le64_to_cpu(l->modifytime)); decode_time(&ino->i_ctime, le64_to_cpu(l->ctime)); decode_time(&i->i_accesstime, le64_to_cpu(l->accesstime)); - ino->i_atime = i->i_accesstime; /* FIXME load from - * accesstime file */ + ino->i_atime = i->i_accesstime; + i->atime_offset = 0; /* Will be filled-in later probably */ + lafs_add_atime_offset(&ino->i_atime, i->atime_offset); ino->i_size = le64_to_cpu(l->size); i->parent = le32_to_cpu(l->parent); ino->i_nlink = le32_to_cpu(l->linkcount); @@ -468,6 +474,75 @@ out: return err; } +static void check_atime_ref(struct inode *ino, int async) +{ + /* If there is an time file in this filesystem the inode + * should hold a reference to the relevant block in + * that file. + */ + struct inode *root, *at; + u32 bnum; + struct datablock *b; + if (async) + /* Never bother for async lookups */ + return; + if (LAFSI(ino)->type < TypeBase) + return; + if (test_bit(I_AccessTime, &LAFSI(ino)->iflags)) + return; + root = ino_from_sb(ino->i_sb); + at = LAFSI(root)->md.fs.accesstime; + if (at == NULL) + return; + + if (LAFSI(ino)->md.file.atime_offset) + LAFSI(ino)->md.file.atime_offset = 0; + + /* "* 2" to get byte number, then shift to get block + * number + */ + bnum = ino->i_ino >> (at->i_blkbits-1); + b = lafs_get_block(at, bnum, NULL, GFP_NOFS, MKREF(atime)); + if (b) { + if (lafs_read_block(b) == 0) { + u16 *atp; + int i; + atp = map_dblock(b); + i = (ino->i_ino * 2) & ((1<i_blkbits)-1); + LAFSI(ino)->md.file.atime_offset = le16_to_cpu(atp[i]); + set_bit(I_AccessTime, &LAFSI(ino)->iflags); + unmap_dblock(b, atp); + lafs_add_atime_offset(&ino->i_atime, + LAFSI(ino)->md.file.atime_offset); + } else + putdref(b, MKREF(atime)); + } +} + +void lafs_add_atime_offset(struct timespec *atime, int offset) +{ + int expon; + time_t mantissa; + if (offset == 0) + return; + + expon = offset & 0x1f; + if (expon) + mantissa = (offset >> 5) | 0x800; + else + mantissa = (offset >> 5); + if (expon >= 11) { + /* seconds */ + mantissa <<= expon-11; + atime->tv_sec += mantissa; + } else { + /* milliseconds */ + if (expon) + mantissa <<= expon-1; + timespec_add_ns(atime, (s64)mantissa * 1000000); + } +} + void lafs_inode_checkpin(struct inode *ino) { /* Make sure I_Pinned is set correctly. diff --git a/lafs.h b/lafs.h index c8c7684..b9b7804 100644 --- a/lafs.h +++ b/lafs.h @@ -136,6 +136,7 @@ void lafs_super_write(struct fs *fs, int dev, u64 addr, char *buf, int size); int lafs_super_wait(struct fs *fs); /* inode.c */ +void lafs_add_atime_offset(struct timespec *atime, int offset); int __must_check lafs_mount(struct fs *fs); struct inode *lafs_iget(struct super_block *fs, ino_t inum, int async); struct inode *lafs_iget_fs(struct fs *fs, int fsnum, int inum, int async); diff --git a/state.h b/state.h index ecbc996..8f27841 100644 --- a/state.h +++ b/state.h @@ -571,6 +571,9 @@ struct lafs_inode { #define I_Pinned 6 /* InoIdx is pinned, i_nlink is non-zero, and consequently * we own an extra ref to the inode and superblock. */ +#define I_AccessTime 7 /* Set if this inode holds a reference to the block + * in the accesstime file that holds our atime + */ /* next three indicate if we hold a reference on the relevant qent */ #define I_QUid 8 #define I_QGid 9 @@ -617,6 +620,7 @@ struct lafs_inode { u32 table_size; /* (blocks) */ } segmentusage; struct file_md { + u16 atime_offset; /* value stored in atime file */ u16 flags; /* u16 mode; */ /* u32 uid; */