1 В избранное 0 Ответвления 0

OSCHINA-MIRROR/openeuler-stratovirt

Присоединиться к Gitlife
Откройте для себя и примите участие в публичных проектах с открытым исходным кодом с участием более 10 миллионов разработчиков. Приватные репозитории также полностью бесплатны :)
Присоединиться бесплатно
Это зеркальный репозиторий, синхронизируется ежедневно с исходного репозитория.
В этом репозитории не указан файл с открытой лицензией (LICENSE). При использовании обратитесь к конкретному описанию проекта и его зависимостям в коде.
Клонировать/Скачать
file.rs 5 КБ
Копировать Редактировать Web IDE Исходные данные Просмотреть построчно История
yexiao Отправлено 12 месяцев назад 01ac847
// Copyright (c) 2022 Huawei Technologies Co.,Ltd. All rights reserved.
//
// StratoVirt is licensed under Mulan PSL v2.
// You can use this software according to the terms and conditions of the Mulan
// PSL v2.
// You may obtain a copy of Mulan PSL v2 at:
// http://license.coscl.org.cn/MulanPSL2
// THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY
// KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
// NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
// See the Mulan PSL v2 for more details.
use std::fs::{remove_file, File, OpenOptions};
use std::os::unix::fs::OpenOptionsExt;
use std::os::unix::io::AsRawFd;
use std::path::Path;
use anyhow::{bail, Context, Ok, Result};
use nix::fcntl::{fcntl, FcntlArg};
use nix::unistd::getpid;
const MIN_FILE_ALIGN: u32 = 512;
pub const MAX_FILE_ALIGN: u32 = 4096;
/// Permission to read
const FILE_LOCK_READ: u64 = 0x01;
/// Permission to write
const FILE_LOCK_WRITE: u64 = 0x02;
/// All permissions
const FILE_LOCK_ALL: [u64; 2] = [FILE_LOCK_READ, FILE_LOCK_WRITE];
/// Permission lock base address, consistent with qemu
const LOCK_PERM_BASE: u64 = 100;
/// Shared lock base address, consistent with qemu
const LOCK_SHARED_BASE: u64 = 200;
pub fn open_file(path: &str, read_only: bool, direct: bool) -> Result<File> {
let mut options = OpenOptions::new();
options.read(true).write(!read_only);
if direct {
options.custom_flags(libc::O_DIRECT);
}
let file = options.open(path).with_context(|| {
format!(
"failed to open the file for block {}. Error: {}",
path,
std::io::Error::last_os_error(),
)
})?;
Ok(file)
}
fn is_io_aligned(file: &File, buf: u64, size: usize) -> bool {
// SAFETY: file and buf is valid.
let ret = unsafe {
libc::pread(
file.as_raw_fd() as libc::c_int,
buf as *mut libc::c_void,
size as libc::size_t,
0,
)
};
ret >= 0 || nix::errno::errno() != libc::EINVAL
}
pub fn get_file_alignment(file: &File, direct: bool) -> (u32, u32) {
if !direct {
return (1, 1);
}
let mut req_align = 0;
let mut buf_align = 0;
// SAFETY: we allocate aligned memory and free it later.
let aligned_buffer = unsafe {
libc::memalign(
MAX_FILE_ALIGN as libc::size_t,
(MAX_FILE_ALIGN * 2) as libc::size_t,
)
};
// Guess alignment requirement of request.
let mut align = MIN_FILE_ALIGN;
while align <= MAX_FILE_ALIGN {
if is_io_aligned(file, aligned_buffer as u64, align as usize) {
req_align = align;
break;
}
align <<= 1;
}
// Guess alignment requirement of buffer.
let mut align = MIN_FILE_ALIGN;
while align <= MAX_FILE_ALIGN {
if is_io_aligned(
file,
aligned_buffer as u64 + align as u64,
MAX_FILE_ALIGN as usize,
) {
buf_align = align;
break;
}
align <<= 1;
}
// SAFETY: the memory is allocated by us and will not be used anymore.
unsafe { libc::free(aligned_buffer) };
(req_align, buf_align)
}
fn do_fcntl_lock(
file: &File,
path: &str,
lockname: &str,
flock: libc::flock,
is_lock: bool,
) -> Result<()> {
let err = match fcntl(file.as_raw_fd(), FcntlArg::F_SETLK(&flock)) {
Err(e) => e,
_ => return Ok(()),
};
if is_lock {
bail!(
"Failed to get {} on file: {}. Is it used more than once or \
another process using the same file? Error: {}",
lockname,
path,
err as i32,
);
} else {
bail!(
"Failed to release lock on file: {}. Error: {}",
path,
err as i32,
);
}
}
fn lock_or_unlock_file(
file: &File,
path: &str,
lock_op: i16,
lock_name: &str,
is_lock: bool,
) -> Result<()> {
let pid = getpid().as_raw();
let mut flock = libc::flock {
l_whence: libc::SEEK_SET as i16,
l_len: 1,
l_pid: pid,
l_type: lock_op,
l_start: 0,
};
for lock in FILE_LOCK_ALL {
flock.l_start = (LOCK_PERM_BASE + lock) as i64;
do_fcntl_lock(file, path, lock_name, flock, is_lock)?;
}
flock.l_start = (LOCK_SHARED_BASE + FILE_LOCK_WRITE) as i64;
do_fcntl_lock(file, path, lock_name, flock, is_lock)?;
Ok(())
}
pub fn lock_file(file: &File, path: &str, read_only: bool) -> Result<()> {
let (lock_op, lock_name) = if read_only {
(libc::F_RDLCK, "read lock")
} else {
(libc::F_WRLCK, "write lock")
};
lock_or_unlock_file(file, path, lock_op as i16, lock_name, true)
}
pub fn unlock_file(file: &File, path: &str) -> Result<()> {
lock_or_unlock_file(file, path, libc::F_UNLCK as i16, "", false)
}
pub fn clear_file(path: String) -> Result<()> {
if Path::new(&path).exists() {
remove_file(&path)
.with_context(|| format!("File {} exists, but failed to remove it.", &path))?;
}
Ok(())
}

Комментарий ( 0 )

Вы можете оставить комментарий после Вход в систему

1
https://gitlife.ru/oschina-mirror/openeuler-stratovirt.git
git@gitlife.ru:oschina-mirror/openeuler-stratovirt.git
oschina-mirror
openeuler-stratovirt
openeuler-stratovirt
master