Add support for the mode of fallocate
This commit is contained in:
parent
99688183f0
commit
29eed82a7e
2
deps/sefs
vendored
2
deps/sefs
vendored
@ -1 +1 @@
|
||||
Subproject commit 8d999ffdf066cc0601c5a726ccfcca75437ced0b
|
||||
Subproject commit 0a17ee1ec824181c1cf2db97a05f612e96879645
|
1
src/libos/Cargo.lock
generated
1
src/libos/Cargo.lock
generated
@ -417,6 +417,7 @@ dependencies = [
|
||||
name = "rcore-fs"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"spin",
|
||||
]
|
||||
|
||||
|
@ -97,6 +97,7 @@ impl ToErrno for rcore_fs::vfs::FsError {
|
||||
FsError::PermError => EPERM,
|
||||
FsError::NameTooLong => ENAMETOOLONG,
|
||||
FsError::FileTooBig => EFBIG,
|
||||
FsError::OpNotSupported => EOPNOTSUPP,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -91,7 +91,7 @@ pub trait File: Debug + Sync + Send + Any {
|
||||
return_op_unsupported_error!("set_advisory_lock")
|
||||
}
|
||||
|
||||
fn fallocate(&self, _mode: u32, _offset: u64, _len: u64) -> Result<()> {
|
||||
fn fallocate(&self, _flags: FallocateFlags, _offset: usize, _len: usize) -> Result<()> {
|
||||
return_op_unsupported_error!("fallocate")
|
||||
}
|
||||
|
||||
|
@ -1,11 +1,89 @@
|
||||
use super::*;
|
||||
use rcore_fs::vfs::{AllocFlags, FallocateMode};
|
||||
|
||||
pub fn do_fallocate(fd: FileDesc, mode: u32, offset: u64, len: u64) -> Result<()> {
|
||||
pub fn do_fallocate(fd: FileDesc, flags: FallocateFlags, offset: usize, len: usize) -> Result<()> {
|
||||
debug!(
|
||||
"fallocate: fd: {}, mode: {}, offset: {}, len: {}",
|
||||
fd, mode, offset, len
|
||||
"fallocate: fd: {}, flags: {:?}, offset: {}, len: {}",
|
||||
fd, flags, offset, len
|
||||
);
|
||||
let file_ref = current!().file(fd)?;
|
||||
file_ref.fallocate(mode, offset, len)?;
|
||||
file_ref.fallocate(flags, offset, len)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
bitflags! {
|
||||
/// Operation mode flags for fallocate
|
||||
/// Please checkout linux/include/uapi/linux/falloc.h for the details
|
||||
pub struct FallocateFlags: u32 {
|
||||
/// File size will not be changed when extend the file
|
||||
const FALLOC_FL_KEEP_SIZE = 0x01;
|
||||
/// De-allocates range
|
||||
const FALLOC_FL_PUNCH_HOLE = 0x02;
|
||||
/// Remove a range of a file without leaving a hole in the file
|
||||
const FALLOC_FL_COLLAPSE_RANGE = 0x08;
|
||||
/// Convert a range of file to zeros
|
||||
const FALLOC_FL_ZERO_RANGE = 0x10;
|
||||
/// Insert space within the file size without overwriting any existing data
|
||||
const FALLOC_FL_INSERT_RANGE = 0x20;
|
||||
/// Unshare shared blocks within the file size without overwriting any existing data
|
||||
const FALLOC_FL_UNSHARE_RANGE = 0x40;
|
||||
}
|
||||
}
|
||||
|
||||
impl FallocateFlags {
|
||||
pub fn from_u32(raw_flags: u32) -> Result<Self> {
|
||||
let flags =
|
||||
Self::from_bits(raw_flags).ok_or_else(|| errno!(EOPNOTSUPP, "invalid flags"))?;
|
||||
if flags.contains(Self::FALLOC_FL_PUNCH_HOLE) && flags.contains(Self::FALLOC_FL_ZERO_RANGE)
|
||||
{
|
||||
return_errno!(
|
||||
EOPNOTSUPP,
|
||||
"Punch hole and zero range are mutually exclusive"
|
||||
);
|
||||
}
|
||||
if flags.contains(Self::FALLOC_FL_PUNCH_HOLE) && !flags.contains(Self::FALLOC_FL_KEEP_SIZE)
|
||||
{
|
||||
return_errno!(EOPNOTSUPP, "Punch hole must have keep size set");
|
||||
}
|
||||
if flags.contains(Self::FALLOC_FL_COLLAPSE_RANGE)
|
||||
&& !(flags & !Self::FALLOC_FL_COLLAPSE_RANGE).is_empty()
|
||||
{
|
||||
return_errno!(EINVAL, "Collapse range should only be used exclusively");
|
||||
}
|
||||
if flags.contains(Self::FALLOC_FL_INSERT_RANGE)
|
||||
&& !(flags & !Self::FALLOC_FL_INSERT_RANGE).is_empty()
|
||||
{
|
||||
return_errno!(EINVAL, "Insert range should only be used exclusively");
|
||||
}
|
||||
if flags.contains(Self::FALLOC_FL_UNSHARE_RANGE)
|
||||
&& !(flags & !(Self::FALLOC_FL_UNSHARE_RANGE | Self::FALLOC_FL_KEEP_SIZE)).is_empty()
|
||||
{
|
||||
return_errno!(
|
||||
EINVAL,
|
||||
"Unshare range should only be used with allocate mode"
|
||||
);
|
||||
}
|
||||
Ok(flags)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<FallocateFlags> for FallocateMode {
|
||||
fn from(flags: FallocateFlags) -> FallocateMode {
|
||||
if flags.contains(FallocateFlags::FALLOC_FL_PUNCH_HOLE) {
|
||||
FallocateMode::PunchHoleKeepSize
|
||||
} else if flags.contains(FallocateFlags::FALLOC_FL_ZERO_RANGE) {
|
||||
if flags.contains(FallocateFlags::FALLOC_FL_KEEP_SIZE) {
|
||||
FallocateMode::ZeroRangeKeepSize
|
||||
} else {
|
||||
FallocateMode::ZeroRange
|
||||
}
|
||||
} else if flags.contains(FallocateFlags::FALLOC_FL_COLLAPSE_RANGE) {
|
||||
FallocateMode::CollapseRange
|
||||
} else if flags.contains(FallocateFlags::FALLOC_FL_INSERT_RANGE) {
|
||||
FallocateMode::InsertRange
|
||||
} else {
|
||||
let flags = AllocFlags::from_bits_truncate(flags.bits());
|
||||
FallocateMode::Allocate(flags)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -6,7 +6,7 @@ pub use self::chmod::{do_fchmod, do_fchmodat, FileMode};
|
||||
pub use self::chown::{do_fchown, do_fchownat, ChownFlags};
|
||||
pub use self::close::do_close;
|
||||
pub use self::dup::{do_dup, do_dup2, do_dup3};
|
||||
pub use self::fallocate::do_fallocate;
|
||||
pub use self::fallocate::{do_fallocate, FallocateFlags};
|
||||
pub use self::fcntl::{do_fcntl, FcntlCmd};
|
||||
pub use self::file_flags::{AccessMode, CreationFlags, StatusFlags};
|
||||
pub use self::flock::{Flock, FlockType};
|
||||
|
@ -1,5 +1,6 @@
|
||||
use super::*;
|
||||
use crate::net::PollEventFlags;
|
||||
use rcore_fs::vfs::FallocateMode;
|
||||
use rcore_fs_sefs::dev::SefsMac;
|
||||
|
||||
pub struct INodeFile {
|
||||
@ -121,8 +122,12 @@ impl File for INodeFile {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn fallocate(&self, mode: u32, offset: u64, len: u64) -> Result<()> {
|
||||
self.inode.fallocate(mode, offset, len)?;
|
||||
fn fallocate(&self, flags: FallocateFlags, offset: usize, len: usize) -> Result<()> {
|
||||
if !self.access_mode.writable() {
|
||||
return_errno!(EBADF, "File is not opened for writing");
|
||||
}
|
||||
let mode = FallocateMode::from(flags);
|
||||
self.inode.fallocate(&mode, offset, len)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
@ -19,8 +19,9 @@ pub use self::event_file::{AsEvent, EventCreationFlags, EventFile};
|
||||
pub use self::events::{AtomicIoEvents, IoEvents, IoNotifier};
|
||||
pub use self::file::{File, FileRef};
|
||||
pub use self::file_ops::{
|
||||
occlum_ocall_ioctl, AccessMode, BuiltinIoctlNum, CreationFlags, FileMode, Flock, FlockType,
|
||||
IfConf, IoctlCmd, Stat, StatusFlags, StructuredIoctlArgType, StructuredIoctlNum,
|
||||
occlum_ocall_ioctl, AccessMode, BuiltinIoctlNum, CreationFlags, FallocateFlags, FileMode,
|
||||
Flock, FlockType, IfConf, IoctlCmd, Stat, StatusFlags, StructuredIoctlArgType,
|
||||
StructuredIoctlNum,
|
||||
};
|
||||
pub use self::file_table::{FileDesc, FileTable, FileTableEvent, FileTableNotifier};
|
||||
pub use self::fs_ops::Statfs;
|
||||
|
@ -628,12 +628,8 @@ pub fn do_fallocate(fd: FileDesc, mode: u32, offset: off_t, len: off_t) -> Resul
|
||||
"offset was less than 0, or len was less than or equal to 0"
|
||||
);
|
||||
}
|
||||
// Current implementation is just the posix_fallocate
|
||||
// TODO: Support more modes in fallocate
|
||||
if mode != 0 {
|
||||
return_errno!(ENOSYS, "unsupported mode");
|
||||
}
|
||||
file_ops::do_fallocate(fd, mode, offset as u64, len as u64)?;
|
||||
let flags = FallocateFlags::from_u32(mode)?;
|
||||
file_ops::do_fallocate(fd, flags, offset as usize, len as usize)?;
|
||||
Ok(0)
|
||||
}
|
||||
|
||||
|
299
test/file/main.c
299
test/file/main.c
@ -1,3 +1,4 @@
|
||||
#define _GNU_SOURCE
|
||||
#include <sys/stat.h>
|
||||
#include <sys/uio.h>
|
||||
#include <errno.h>
|
||||
@ -9,6 +10,9 @@
|
||||
// Helper function
|
||||
// ============================================================================
|
||||
|
||||
#define KB (1024)
|
||||
#define BLK_SIZE (4 * KB)
|
||||
|
||||
static int create_file(const char *file_path) {
|
||||
int fd;
|
||||
int flags = O_RDONLY | O_CREAT | O_TRUNC;
|
||||
@ -164,12 +168,21 @@ static int __test_lseek(const char *file_path) {
|
||||
}
|
||||
|
||||
static int __test_posix_fallocate(const char *file_path) {
|
||||
int fd = open(file_path, O_RDWR);
|
||||
int fd = open(file_path, O_RDONLY);
|
||||
if (fd < 0) {
|
||||
THROW_ERROR("failed to open a file to read");
|
||||
}
|
||||
if (posix_fallocate(fd, 0, 16) != EBADF) {
|
||||
THROW_ERROR("failed to check the open flags for fallocate");
|
||||
}
|
||||
close(fd);
|
||||
fd = open(file_path, O_RDWR);
|
||||
if (fd < 0) {
|
||||
THROW_ERROR("failed to open a file to read/write");
|
||||
}
|
||||
|
||||
off_t offset = -1;
|
||||
off_t len = 100;
|
||||
off_t len = 128;
|
||||
if (posix_fallocate(fd, offset, len) != EINVAL) {
|
||||
THROW_ERROR("failed to call posix_fallocate with invalid offset");
|
||||
}
|
||||
@ -182,6 +195,7 @@ static int __test_posix_fallocate(const char *file_path) {
|
||||
if (posix_fallocate(fd, offset, len) != 0) {
|
||||
THROW_ERROR("failed to call posix_fallocate");
|
||||
}
|
||||
|
||||
struct stat stat_buf;
|
||||
if (fstat(fd, &stat_buf) < 0) {
|
||||
THROW_ERROR("failed to stat file");
|
||||
@ -203,6 +217,257 @@ static int __test_posix_fallocate(const char *file_path) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifndef __GLIBC__
|
||||
#define FALLOC_FL_COLLAPSE_RANGE (0x08)
|
||||
#define FALLOC_FL_ZERO_RANGE (0x10)
|
||||
#define FALLOC_FL_INSERT_RANGE (0x20)
|
||||
#define FALLOC_FL_UNSHARE_RANGE (0x40)
|
||||
#endif
|
||||
|
||||
static int __test_fallocate_with_invalid_mode(const char *file_path) {
|
||||
int fd = open(file_path, O_RDWR);
|
||||
if (fd < 0) {
|
||||
THROW_ERROR("failed to open a file to read/write");
|
||||
}
|
||||
|
||||
off_t len = 2 * BLK_SIZE;
|
||||
if (fill_file_with_repeated_bytes(fd, len, 0xFF) < 0) {
|
||||
THROW_ERROR("failed to fill file");
|
||||
}
|
||||
|
||||
// Check the mode with expected errno
|
||||
int mode_with_expected_errno[6][2] = {
|
||||
{FALLOC_FL_KEEP_SIZE | 0xDEAD, EOPNOTSUPP},
|
||||
{FALLOC_FL_PUNCH_HOLE | FALLOC_FL_ZERO_RANGE, EOPNOTSUPP},
|
||||
{FALLOC_FL_PUNCH_HOLE, EOPNOTSUPP},
|
||||
{FALLOC_FL_INSERT_RANGE | FALLOC_FL_KEEP_SIZE, EINVAL},
|
||||
{FALLOC_FL_COLLAPSE_RANGE | FALLOC_FL_KEEP_SIZE, EINVAL},
|
||||
{FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE | FALLOC_FL_UNSHARE_RANGE, EINVAL},
|
||||
};
|
||||
int row_cnt = (sizeof(mode_with_expected_errno) / sizeof(int)) /
|
||||
(sizeof(mode_with_expected_errno[0]) / sizeof(int));
|
||||
for (int i = 0; i < row_cnt; i++) {
|
||||
int mode = mode_with_expected_errno[i][0];
|
||||
int expected_errno = mode_with_expected_errno[i][1];
|
||||
off_t offset = 0;
|
||||
off_t half_len = len / 2;
|
||||
errno = 0;
|
||||
|
||||
int ret = fallocate(fd, mode, offset, half_len);
|
||||
if (!(ret < 0 && errno == expected_errno)) {
|
||||
THROW_ERROR("failed to check fallocate with invalid mode");
|
||||
}
|
||||
}
|
||||
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __test_fallocate_keep_size(const char *file_path) {
|
||||
int fd = open(file_path, O_RDWR);
|
||||
if (fd < 0) {
|
||||
THROW_ERROR("failed to open a file to read/write");
|
||||
}
|
||||
|
||||
int mode = FALLOC_FL_KEEP_SIZE;
|
||||
off_t offset = 0;
|
||||
off_t len = 64;
|
||||
if (fallocate(fd, mode, offset, len) < 0) {
|
||||
THROW_ERROR("failed to call fallocate with FALLOC_FL_KEEP_SIZE");
|
||||
}
|
||||
|
||||
struct stat stat_buf;
|
||||
if (fstat(fd, &stat_buf) < 0) {
|
||||
THROW_ERROR("failed to stat file");
|
||||
}
|
||||
if (stat_buf.st_size != 0) {
|
||||
THROW_ERROR("failed to check the len after fallocate");
|
||||
}
|
||||
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __test_fallocate_punch_hole(const char *file_path) {
|
||||
int fd = open(file_path, O_RDWR);
|
||||
if (fd < 0) {
|
||||
THROW_ERROR("failed to open a file to read/write");
|
||||
}
|
||||
|
||||
off_t len = 64;
|
||||
if (fill_file_with_repeated_bytes(fd, len, 0xFF) < 0) {
|
||||
THROW_ERROR("failed to fill file");
|
||||
}
|
||||
|
||||
int mode = FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE;
|
||||
off_t offset = 0;
|
||||
off_t hole_len = len / 2;
|
||||
if (fallocate(fd, mode, offset, hole_len) < 0) {
|
||||
THROW_ERROR("failed to call fallocate with FALLOC_FL_PUNCH_HOLE");
|
||||
}
|
||||
|
||||
struct stat stat_buf;
|
||||
if (fstat(fd, &stat_buf) < 0) {
|
||||
THROW_ERROR("failed to stat file");
|
||||
}
|
||||
if (stat_buf.st_size != len) {
|
||||
THROW_ERROR("failed to check the len after fallocate");
|
||||
}
|
||||
|
||||
if (lseek(fd, offset, SEEK_SET) != offset) {
|
||||
THROW_ERROR("failed to lseek the file");
|
||||
}
|
||||
if (check_file_with_repeated_bytes(fd, hole_len, 0x00) < 0) {
|
||||
THROW_ERROR("failed to check file after punch hole");
|
||||
}
|
||||
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __test_fallocate_zero_range(const char *file_path) {
|
||||
int fd = open(file_path, O_RDWR);
|
||||
if (fd < 0) {
|
||||
THROW_ERROR("failed to open a file to read/write");
|
||||
}
|
||||
|
||||
off_t len = 64;
|
||||
if (fill_file_with_repeated_bytes(fd, len, 0xFF) < 0) {
|
||||
THROW_ERROR("failed to fill file");
|
||||
}
|
||||
|
||||
int mode = FALLOC_FL_ZERO_RANGE;
|
||||
off_t offset = len / 2;
|
||||
off_t zero_len = len * 2;
|
||||
if (fallocate(fd, mode, offset, zero_len) < 0) {
|
||||
THROW_ERROR("failed to call fallocate with FALLOC_FL_ZERO_RANGE");
|
||||
}
|
||||
|
||||
struct stat stat_buf;
|
||||
if (fstat(fd, &stat_buf) < 0) {
|
||||
THROW_ERROR("failed to stat file");
|
||||
}
|
||||
if (stat_buf.st_size != offset + zero_len) {
|
||||
THROW_ERROR("failed to check the len after fallocate");
|
||||
}
|
||||
|
||||
if (lseek(fd, offset, SEEK_SET) != offset) {
|
||||
THROW_ERROR("failed to lseek the file");
|
||||
}
|
||||
if (check_file_with_repeated_bytes(fd, zero_len, 0x00) < 0) {
|
||||
THROW_ERROR("failed to check file after zero range");
|
||||
}
|
||||
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __test_fallocate_insert_range(const char *file_path) {
|
||||
int fd = open(file_path, O_RDWR);
|
||||
if (fd < 0) {
|
||||
THROW_ERROR("failed to open a file to read/write");
|
||||
}
|
||||
|
||||
off_t len = 4 * BLK_SIZE;
|
||||
if (fill_file_with_repeated_bytes(fd, len, 0xFF) < 0) {
|
||||
THROW_ERROR("failed to fill file");
|
||||
}
|
||||
|
||||
int mode = FALLOC_FL_INSERT_RANGE;
|
||||
off_t offset = len;
|
||||
off_t insert_len = len / 4;
|
||||
int ret = fallocate(fd, mode, offset, insert_len);
|
||||
if (ret >= 0 || errno != EINVAL ) {
|
||||
THROW_ERROR("failed to check insert range with oversized offset");
|
||||
}
|
||||
|
||||
// make the offset is not the multiple of the filesystem block size
|
||||
offset += 1;
|
||||
ret = fallocate(fd, mode, offset, insert_len);
|
||||
if (ret >= 0 || errno != EINVAL ) {
|
||||
THROW_ERROR("failed to check insert range with invalid offset");
|
||||
}
|
||||
|
||||
offset = len / 4;
|
||||
if (fallocate(fd, mode, offset, insert_len) < 0) {
|
||||
THROW_ERROR("failed to call fallocate with FALLOC_FL_INSERT_RANGE");
|
||||
}
|
||||
|
||||
struct stat stat_buf;
|
||||
if (fstat(fd, &stat_buf) < 0) {
|
||||
THROW_ERROR("failed to stat file");
|
||||
}
|
||||
if (stat_buf.st_size != len + insert_len) {
|
||||
THROW_ERROR("failed to check the len after fallocate");
|
||||
}
|
||||
|
||||
if (lseek(fd, offset, SEEK_SET) != offset) {
|
||||
THROW_ERROR("failed to lseek the file");
|
||||
}
|
||||
if (check_file_with_repeated_bytes(fd, insert_len, 0x00) < 0) {
|
||||
THROW_ERROR("failed to check inserted contents after insert range");
|
||||
}
|
||||
if (lseek(fd, offset + insert_len, SEEK_SET) != offset + insert_len) {
|
||||
THROW_ERROR("failed to lseek the file");
|
||||
}
|
||||
if (check_file_with_repeated_bytes(fd, len - offset, 0xFF) < 0) {
|
||||
THROW_ERROR("failed to check shifted contents after insert range");
|
||||
}
|
||||
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __test_fallocate_collapse_range(const char *file_path) {
|
||||
int fd = open(file_path, O_RDWR);
|
||||
if (fd < 0) {
|
||||
THROW_ERROR("failed to open a file to read/write");
|
||||
}
|
||||
|
||||
off_t len = 4 * BLK_SIZE;
|
||||
if (fill_file_with_repeated_bytes(fd, len, 0xFF) < 0) {
|
||||
THROW_ERROR("failed to fill file");
|
||||
}
|
||||
|
||||
int mode = FALLOC_FL_COLLAPSE_RANGE;
|
||||
off_t offset = len / 4;
|
||||
off_t collapse_len = len;
|
||||
int ret = fallocate(fd, mode, offset, collapse_len);
|
||||
if (ret >= 0 || errno != EINVAL ) {
|
||||
THROW_ERROR("failed to check collapse range with oversized end_offset");
|
||||
}
|
||||
|
||||
// make the collapse_len is not the multiple of the filesystem block size
|
||||
collapse_len = len / 4 + 1;
|
||||
ret = fallocate(fd, mode, offset, collapse_len);
|
||||
if (ret >= 0 || errno != EINVAL ) {
|
||||
THROW_ERROR("failed to check collapse range with invalid collapse_len");
|
||||
}
|
||||
|
||||
collapse_len = len / 4;
|
||||
if (fallocate(fd, mode, offset, collapse_len) < 0) {
|
||||
THROW_ERROR("failed to call fallocate with FALLOC_FL_COLLAPSE_RANGE");
|
||||
}
|
||||
|
||||
struct stat stat_buf;
|
||||
if (fstat(fd, &stat_buf) < 0) {
|
||||
THROW_ERROR("failed to stat file");
|
||||
}
|
||||
if (stat_buf.st_size != len - collapse_len) {
|
||||
THROW_ERROR("failed to check the len after fallocate");
|
||||
}
|
||||
|
||||
if (lseek(fd, offset, SEEK_SET) != offset) {
|
||||
THROW_ERROR("failed to lseek the file");
|
||||
}
|
||||
if (check_file_with_repeated_bytes(fd, len - offset - collapse_len, 0xFF) < 0) {
|
||||
THROW_ERROR("failed to check the moved contents after collapse range");
|
||||
}
|
||||
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
typedef int(*test_file_func_t)(const char *);
|
||||
|
||||
static int test_file_framework(test_file_func_t fn) {
|
||||
@ -240,6 +505,30 @@ static int test_posix_fallocate() {
|
||||
return test_file_framework(__test_posix_fallocate);
|
||||
}
|
||||
|
||||
static int test_fallocate_with_invalid_mode() {
|
||||
return test_file_framework(__test_fallocate_with_invalid_mode);
|
||||
}
|
||||
|
||||
static int test_fallocate_keep_size() {
|
||||
return test_file_framework(__test_fallocate_keep_size);
|
||||
}
|
||||
|
||||
static int test_fallocate_punch_hole() {
|
||||
return test_file_framework(__test_fallocate_punch_hole);
|
||||
}
|
||||
|
||||
static int test_fallocate_zero_range() {
|
||||
return test_file_framework(__test_fallocate_zero_range);
|
||||
}
|
||||
|
||||
static int test_fallocate_insert_range() {
|
||||
return test_file_framework(__test_fallocate_insert_range);
|
||||
}
|
||||
|
||||
static int test_fallocate_collapse_range() {
|
||||
return test_file_framework(__test_fallocate_collapse_range);
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Test suite main
|
||||
// ============================================================================
|
||||
@ -250,6 +539,12 @@ static test_case_t test_cases[] = {
|
||||
TEST_CASE(test_writev_readv),
|
||||
TEST_CASE(test_lseek),
|
||||
TEST_CASE(test_posix_fallocate),
|
||||
TEST_CASE(test_fallocate_with_invalid_mode),
|
||||
TEST_CASE(test_fallocate_keep_size),
|
||||
TEST_CASE(test_fallocate_punch_hole),
|
||||
TEST_CASE(test_fallocate_zero_range),
|
||||
TEST_CASE(test_fallocate_insert_range),
|
||||
TEST_CASE(test_fallocate_collapse_range),
|
||||
};
|
||||
|
||||
int main(int argc, const char *argv[]) {
|
||||
|
@ -76,22 +76,20 @@ int fill_file_with_repeated_bytes(int fd, size_t len, int byte_val) {
|
||||
}
|
||||
|
||||
int check_file_with_repeated_bytes(int fd, size_t len, int expected_byte_val) {
|
||||
size_t remain = len;
|
||||
int remain = len;
|
||||
char read_buf[512];
|
||||
while (remain > 0) {
|
||||
int read_nbytes = read(fd, read_buf, sizeof(read_buf));
|
||||
if (read_nbytes < 0) {
|
||||
// I/O error
|
||||
return -1;
|
||||
THROW_ERROR("I/O error");
|
||||
}
|
||||
size_t check_nbytes = remain < read_nbytes ? remain : read_nbytes;
|
||||
remain -= read_nbytes;
|
||||
if (read_nbytes == 0 && remain > 0) {
|
||||
// Not enough data in the file
|
||||
return -1;
|
||||
THROW_ERROR("Not enough data in the file");
|
||||
}
|
||||
if (check_bytes_in_buf(read_buf, read_nbytes, expected_byte_val) < 0) {
|
||||
// Incorrect data
|
||||
return -1;
|
||||
if (check_bytes_in_buf(read_buf, check_nbytes, expected_byte_val) < 0) {
|
||||
THROW_ERROR("Incorrect data");
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
|
Loading…
Reference in New Issue
Block a user