Commit d2256b3e authored by AdminXVII's avatar AdminXVII Committed by Jeremy Soller

Add tracking of access times

Add the atime field, which tracks the last access time. Only reads
update the atime.

**BREAKING CHANGE**: One less extent available per block, 4 more bytes
for node names.
parent 3191d7d1
......@@ -97,7 +97,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "redoxfs"
version = "0.3.7"
version = "0.4.0"
dependencies = [
"fuse 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
......
......@@ -2,7 +2,7 @@
name = "redoxfs"
description = "The Redox Filesystem"
repository = "https://gitlab.redox-os.org/redox-os/redoxfs"
version = "0.3.7"
version = "0.4.0"
license-file = "LICENSE"
readme = "README.md"
authors = ["Jeremy Soller <jackpot51@gmail.com>"]
......
use std::cmp::min;
use std::time::{SystemTime, UNIX_EPOCH};
use syscall::error::{Result, Error, EEXIST, EISDIR, EINVAL, ENOENT, ENOSPC, ENOTDIR, ENOTEMPTY};
......@@ -428,6 +429,7 @@ impl<D: Disk> FileSystem<D> {
}
pub fn read_node(&mut self, block: u64, offset: u64, buf: &mut [u8]) -> Result<usize> {
let atime = SystemTime::now().duration_since(UNIX_EPOCH).unwrap();
let block_offset = offset / BLOCK_SIZE;
let mut byte_offset = (offset % BLOCK_SIZE) as usize;
......@@ -483,6 +485,20 @@ impl<D: Disk> FileSystem<D> {
assert_eq!(block, extent.block + (extent.length + BLOCK_SIZE - 1)/BLOCK_SIZE);
}
if i > 0 {
let atime_nsec = atime.subsec_nanos();
let atime = atime.as_secs();
let mut node = self.node(block)?;
if atime > node.1.atime || (atime == node.1.atime && atime_nsec > node.1.atime_nsec) {
let is_old = atime - node.1.atime > 3600; // Last read was more than a day ago
node.1.atime = atime;
node.1.atime_nsec = atime_nsec;
if is_old {
self.write_at(node.0, &node.1)?;
}
}
}
Ok(i)
}
......
#![crate_name="redoxfs"]
#![crate_type="lib"]
#![crate_name = "redoxfs"]
#![crate_type = "lib"]
extern crate syscall;
extern crate uuid;
......@@ -8,7 +8,7 @@ use std::sync::atomic::AtomicUsize;
pub const BLOCK_SIZE: u64 = 4096;
pub const SIGNATURE: &'static [u8; 8] = b"RedoxFS\0";
pub const VERSION: u64 = 3;
pub const VERSION: u64 = 4;
pub static IS_UMT: AtomicUsize = AtomicUsize::new(0);
pub use self::archive::{archive, archive_at};
......
......@@ -117,7 +117,7 @@ impl<D: Disk> Filesystem for Fuse<D> {
fn setattr(&mut self, _req: &Request, block: u64, mode: Option<u32>,
uid: Option<u32>, gid: Option<u32>, size: Option<u64>,
_atime: Option<Timespec>, mtime: Option<Timespec>, _fh: Option<u64>,
atime: Option<Timespec>, mtime: Option<Timespec>, _fh: Option<u64>,
_crtime: Option<Timespec>, _chgtime: Option<Timespec>, _bkuptime: Option<Timespec>,
_flags: Option<u32>, reply: ReplyAttr) {
if let Some(mode) = mode {
......@@ -176,11 +176,20 @@ impl<D: Disk> Filesystem for Fuse<D> {
}
}
if let Some(mtime) = mtime {
let need_update = atime.is_some() || mtime.is_some();
if need_update {
match self.fs.node(block) {
Ok(mut node) => {
node.1.mtime = mtime.sec as u64;
node.1.mtime_nsec = mtime.nsec as u32;
if let Some(atime) = atime {
node.1.atime = atime.sec as u64;
node.1.atime_nsec = atime.nsec as u32;
}
if let Some(mtime) = mtime {
node.1.mtime = mtime.sec as u64;
node.1.mtime_nsec = mtime.nsec as u32;
}
if let Err(err) = self.fs.write_at(node.0, &node.1) {
reply.error(err.errno as i32);
return;
......
......@@ -165,6 +165,8 @@ impl<D: Disk> Resource<D> for DirResource {
st_size: fs.node_len(self.block)?,
st_mtime: node.1.mtime,
st_mtime_nsec: node.1.mtime_nsec,
st_atime: node.1.atime,
st_atime_nsec: node.1.atime_nsec,
st_ctime: node.1.ctime,
st_ctime_nsec: node.1.ctime_nsec,
..Default::default()
......@@ -426,6 +428,8 @@ impl<D: Disk> Resource<D> for FileResource {
st_size: fs.node_len(self.block)?,
st_mtime: node.1.mtime,
st_mtime_nsec: node.1.mtime_nsec,
st_atime: node.1.atime,
st_atime_nsec: node.1.atime_nsec,
st_ctime: node.1.ctime,
st_ctime_nsec: node.1.ctime_nsec,
..Default::default()
......@@ -455,17 +459,16 @@ impl<D: Disk> Resource<D> for FileResource {
let mut node = fs.node(self.block)?;
if node.1.uid == self.uid || self.uid == 0 {
if let Some(mtime) = times.get(1) {
if let &[atime, mtime] = times {
node.1.mtime = mtime.tv_sec as u64;
node.1.mtime_nsec = mtime.tv_nsec as u32;
node.1.atime = atime.tv_sec as u64;
node.1.atime_nsec = atime.tv_nsec as u32;
fs.write_at(node.0, &node.1)?;
Ok(0)
} else {
Ok(0)
}
Ok(0)
} else {
Err(Error::new(EPERM))
}
......
......@@ -14,10 +14,12 @@ pub struct Node {
pub ctime_nsec: u32,
pub mtime: u64,
pub mtime_nsec: u32,
pub name: [u8; 222],
pub atime: u64,
pub atime_nsec: u32,
pub name: [u8; 226],
pub parent: u64,
pub next: u64,
pub extents: [Extent; (BLOCK_SIZE as usize - 272)/16],
pub extents: [Extent; (BLOCK_SIZE as usize - 288)/16],
}
impl Node {
......@@ -40,15 +42,17 @@ impl Node {
ctime_nsec: 0,
mtime: 0,
mtime_nsec: 0,
name: [0; 222],
atime: 0,
atime_nsec: 0,
name: [0; 226],
parent: 0,
next: 0,
extents: [Extent::default(); (BLOCK_SIZE as usize - 272)/16],
extents: [Extent::default(); (BLOCK_SIZE as usize - 288)/16],
}
}
pub fn new(mode: u16, name: &str, parent: u64, ctime: u64, ctime_nsec: u32) -> syscall::Result<Node> {
let mut bytes = [0; 222];
let mut bytes = [0; 226];
if name.len() > bytes.len() {
return Err(syscall::Error::new(syscall::ENAMETOOLONG));
}
......@@ -64,10 +68,12 @@ impl Node {
ctime_nsec: ctime_nsec,
mtime: ctime,
mtime_nsec: ctime_nsec,
atime: ctime,
atime_nsec: ctime_nsec,
name: bytes,
parent: parent,
next: 0,
extents: [Extent::default(); (BLOCK_SIZE as usize - 272)/16],
extents: [Extent::default(); (BLOCK_SIZE as usize - 288)/16],
})
}
......@@ -85,7 +91,7 @@ impl Node {
}
pub fn set_name(&mut self, name: &str) -> syscall::Result<()> {
let mut bytes = [0; 222];
let mut bytes = [0; 226];
if name.len() > bytes.len() {
return Err(syscall::Error::new(syscall::ENAMETOOLONG));
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment