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.
This commit is contained in:
Generated
+1
-1
@@ -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)",
|
||||
|
||||
+1
-1
@@ -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>"]
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
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)
|
||||
}
|
||||
|
||||
|
||||
+3
-3
@@ -1,5 +1,5 @@
|
||||
#![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};
|
||||
|
||||
+13
-4
@@ -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))
|
||||
}
|
||||
|
||||
+13
-7
@@ -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));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user