diff --git a/crates/libcontainer/src/syscall/linux.rs b/crates/libcontainer/src/syscall/linux.rs index d01c4a5457..0e74d6d8b7 100644 --- a/crates/libcontainer/src/syscall/linux.rs +++ b/crates/libcontainer/src/syscall/linux.rs @@ -100,7 +100,7 @@ impl FromStr for MountAttrOption { MOUNT_ATTR_RELATIME, )), "rnoatime" => Ok(MountAttrOption::MountAttrNoatime(false, MOUNT_ATTR_NOATIME)), - "ratime" => Ok(MountAttrOption::MountAttrNoatime(true, MOUNT_ATTR_NOATIME)), + "ratime" => Ok(MountAttrOption::MountAttrNoatime(true, MOUNT_ATTR__ATIME)), "rstrictatime" => Ok(MountAttrOption::MountAttrStrictAtime( false, MOUNT_ATTR_STRICTATIME, diff --git a/tests/contest/contest/src/tests/mounts_recursive/mod.rs b/tests/contest/contest/src/tests/mounts_recursive/mod.rs index ba3f5b1e30..6109ccb082 100644 --- a/tests/contest/contest/src/tests/mounts_recursive/mod.rs +++ b/tests/contest/contest/src/tests/mounts_recursive/mod.rs @@ -182,13 +182,13 @@ fn check_recursive_nosuid() -> TestResult { Some(Uid::from_raw(1200)), None, ) - .unwrap(); + .unwrap(); chown( &in_container_executable_subdir_file_path, Some(Uid::from_raw(1200)), None, ) - .unwrap(); + .unwrap(); in_container_executable_file_perm .set_mode(in_container_executable_file_perm.mode() | Mode::S_ISUID.bits()); in_container_executable_subdir_file_perm @@ -503,6 +503,29 @@ fn check_recursive_rnoatime() -> TestResult { result } +fn check_recursive_ratime() -> TestResult { + let ratime_dir_path = PathBuf::from_str("/tmp/ratime_dir").unwrap(); + let mount_dest_path = PathBuf::from_str("/ratime").unwrap(); + fs::create_dir(ratime_dir_path.clone()).unwrap(); + + let mount_options = vec!["rbind".to_string(), "ratime".to_string()]; + let mut mount_spec = Mount::default(); + mount_spec + .set_destination(mount_dest_path) + .set_typ(None) + .set_source(Some(ratime_dir_path.clone())) + .set_options(Some(mount_options)); + let spec = get_spec( + vec![mount_spec], + vec!["runtimetest".to_string(), "mounts_recursive".to_string()], + ); + + let result = test_inside_container(spec, &|_| Ok(())); + + fs::remove_dir_all(ratime_dir_path).unwrap(); + result +} + fn check_recursive_rstrictatime() -> TestResult { let rstrictatime_base_dir = PathBuf::from_str("/tmp").unwrap(); let rstrictatime_dir_path = rstrictatime_base_dir.join("rstrictatime_dir"); @@ -622,6 +645,7 @@ pub fn get_mounts_recursive_test() -> TestGroup { let rrelatime_test = Test::new("rrelatime_test", Box::new(check_recursive_rrelatime)); let rnorelatime_test = Test::new("rnorelatime_test", Box::new(check_recursive_rnorelatime)); let rnoatime_test = Test::new("rnoatime_test", Box::new(check_recursive_rnoatime)); + let ratime_test = Test::new("ratime_test", Box::new(check_recursive_ratime)); let rstrictatime_test = Test::new("rstrictatime_test", Box::new(check_recursive_rstrictatime)); let rnosymfollow_test = Test::new("rnosymfollow_test", Box::new(check_recursive_rnosymfollow)); let rsymfollow_test = Test::new("rsymfollow_test", Box::new(check_recursive_rsymfollow)); @@ -641,6 +665,7 @@ pub fn get_mounts_recursive_test() -> TestGroup { Box::new(rrelatime_test), Box::new(rnorelatime_test), Box::new(rnoatime_test), + Box::new(ratime_test), Box::new(rstrictatime_test), Box::new(rnosymfollow_test), Box::new(rsymfollow_test), diff --git a/tests/contest/runtimetest/src/tests.rs b/tests/contest/runtimetest/src/tests.rs index dee3afc796..6b257ba610 100644 --- a/tests/contest/runtimetest/src/tests.rs +++ b/tests/contest/runtimetest/src/tests.rs @@ -254,6 +254,16 @@ pub fn validate_mounts_recursive(spec: &Spec) { ); } } + "ratime" => { + println!("ratime: {mount:?}"); + if let Err(e) = utils::test_mount_ratime_option( + mount.destination().to_str().unwrap(), + ) { + eprintln!( + "path expected to be ratime, found not ratime, error: {e}" + ); + } + } "rstrictatime" => { println!("rstrictatime: {mount:?}"); if let Err(e) = utils::test_mount_rstrictatime_option( diff --git a/tests/contest/runtimetest/src/utils.rs b/tests/contest/runtimetest/src/utils.rs index ab991a079f..8ec2d89c19 100644 --- a/tests/contest/runtimetest/src/utils.rs +++ b/tests/contest/runtimetest/src/utils.rs @@ -340,6 +340,46 @@ pub fn test_mount_rnoatime_option(path: &str) -> Result<(), std::io::Error> { Ok(()) } +pub fn test_mount_ratime_option(path: &str) -> Result<(), std::io::Error> { + let test_file_path = PathBuf::from(path).join("ratime.txt"); + Command::new("touch") + .arg(test_file_path.to_str().unwrap()) + .output()?; + let one_metadata = fs::metadata(test_file_path.clone())?; + println!( + "{:?} file one atime is {:?},mtime is {:?}, current time is {:?}", + test_file_path, + one_metadata.atime(), + one_metadata.mtime(), + std::time::SystemTime::now() + ); + std::thread::sleep(std::time::Duration::from_millis(1000)); + + // execute touch command to update access time + Command::new("touch") + .arg(test_file_path.to_str().unwrap()) + .output() + .expect("execute touch command error"); + let two_metadata = fs::metadata(test_file_path.clone())?; + println!( + "{:?} file two atime is {:?},mtime is {:?},current time is {:?}", + test_file_path, + two_metadata.atime(), + two_metadata.mtime(), + std::time::SystemTime::now() + ); + if one_metadata.atime() == two_metadata.atime() { + return Err(std::io::Error::new( + std::io::ErrorKind::Other, + format!( + "update access time for file {:?}, expected update", + test_file_path.to_str() + ), + )); + } + Ok(()) +} + // Always update the last access time (atime) when files are accessed on this mount. pub fn test_mount_rstrictatime_option(path: &str) -> Result<(), std::io::Error> { let test_file_path = PathBuf::from(path).join("rstrictatime.txt");