Add a dummy implementation for file advisory locks
This commits is a dummy implementation of file advisory locks. Specifically, for regular files, fcntl `F_SETLK` (i.e., acquiring or releasing locks) always succeeds and fcntl `F_GETLK` (i.e., testing locks) always returns no locks.
This commit is contained in:
		
							parent
							
								
									a6e55881b9
								
							
						
					
					
						commit
						551fb8f9d8
					
				| @ -79,6 +79,14 @@ pub trait File: Debug + Sync + Send + Any { | |||||||
|         return_op_unsupported_error!("set_status_flags") |         return_op_unsupported_error!("set_status_flags") | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     fn test_advisory_lock(&self, lock: &mut Flock) -> Result<()> { | ||||||
|  |         return_op_unsupported_error!("test_advisory_lock") | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     fn set_advisory_lock(&self, lock: &Flock) -> Result<()> { | ||||||
|  |         return_op_unsupported_error!("set_advisory_lock") | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     fn as_any(&self) -> &dyn Any; |     fn as_any(&self) -> &dyn Any; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -1,7 +1,9 @@ | |||||||
|  | use super::flock::flock; | ||||||
| use super::*; | use super::*; | ||||||
|  | use util::mem_util::from_user; | ||||||
| 
 | 
 | ||||||
| #[derive(Debug)] | #[derive(Debug)] | ||||||
| pub enum FcntlCmd { | pub enum FcntlCmd<'a> { | ||||||
|     /// Duplicate the file descriptor fd using the lowest-numbered available
 |     /// Duplicate the file descriptor fd using the lowest-numbered available
 | ||||||
|     /// file descriptor greater than or equal to arg.
 |     /// file descriptor greater than or equal to arg.
 | ||||||
|     DupFd(FileDesc), |     DupFd(FileDesc), | ||||||
| @ -16,11 +18,15 @@ pub enum FcntlCmd { | |||||||
|     GetFl(), |     GetFl(), | ||||||
|     /// Set the file status flags
 |     /// Set the file status flags
 | ||||||
|     SetFl(u32), |     SetFl(u32), | ||||||
|  |     /// Test a file lock
 | ||||||
|  |     GetLk(&'a mut flock), | ||||||
|  |     /// Acquire or release a file lock
 | ||||||
|  |     SetLk(&'a flock), | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl FcntlCmd { | impl<'a> FcntlCmd<'a> { | ||||||
|     #[deny(unreachable_patterns)] |     #[deny(unreachable_patterns)] | ||||||
|     pub fn from_raw(cmd: u32, arg: u64) -> Result<FcntlCmd> { |     pub fn from_raw(cmd: u32, arg: u64) -> Result<FcntlCmd<'a>> { | ||||||
|         Ok(match cmd as c_int { |         Ok(match cmd as c_int { | ||||||
|             libc::F_DUPFD => FcntlCmd::DupFd(arg as FileDesc), |             libc::F_DUPFD => FcntlCmd::DupFd(arg as FileDesc), | ||||||
|             libc::F_DUPFD_CLOEXEC => FcntlCmd::DupFdCloexec(arg as FileDesc), |             libc::F_DUPFD_CLOEXEC => FcntlCmd::DupFdCloexec(arg as FileDesc), | ||||||
| @ -28,12 +34,24 @@ impl FcntlCmd { | |||||||
|             libc::F_SETFD => FcntlCmd::SetFd(arg as u32), |             libc::F_SETFD => FcntlCmd::SetFd(arg as u32), | ||||||
|             libc::F_GETFL => FcntlCmd::GetFl(), |             libc::F_GETFL => FcntlCmd::GetFl(), | ||||||
|             libc::F_SETFL => FcntlCmd::SetFl(arg as u32), |             libc::F_SETFL => FcntlCmd::SetFl(arg as u32), | ||||||
|  |             libc::F_GETLK => { | ||||||
|  |                 let flock_mut_ptr = arg as *mut flock; | ||||||
|  |                 from_user::check_mut_ptr(flock_mut_ptr)?; | ||||||
|  |                 let flock_mut_c = unsafe { &mut *flock_mut_ptr }; | ||||||
|  |                 FcntlCmd::GetLk(flock_mut_c) | ||||||
|  |             } | ||||||
|  |             libc::F_SETLK => { | ||||||
|  |                 let flock_ptr = arg as *const flock; | ||||||
|  |                 from_user::check_ptr(flock_ptr)?; | ||||||
|  |                 let flock_c = unsafe { &*flock_ptr }; | ||||||
|  |                 FcntlCmd::SetLk(flock_c) | ||||||
|  |             } | ||||||
|             _ => return_errno!(EINVAL, "unsupported command"), |             _ => return_errno!(EINVAL, "unsupported command"), | ||||||
|         }) |         }) | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| pub fn do_fcntl(fd: FileDesc, cmd: &FcntlCmd) -> Result<isize> { | pub fn do_fcntl(fd: FileDesc, cmd: &mut FcntlCmd) -> Result<isize> { | ||||||
|     info!("fcntl: fd: {:?}, cmd: {:?}", &fd, cmd); |     info!("fcntl: fd: {:?}, cmd: {:?}", &fd, cmd); | ||||||
|     let current_ref = process::get_current(); |     let current_ref = process::get_current(); | ||||||
|     let mut current = current_ref.lock().unwrap(); |     let mut current = current_ref.lock().unwrap(); | ||||||
| @ -59,7 +77,7 @@ pub fn do_fcntl(fd: FileDesc, cmd: &FcntlCmd) -> Result<isize> { | |||||||
|         } |         } | ||||||
|         FcntlCmd::SetFd(fd_flags) => { |         FcntlCmd::SetFd(fd_flags) => { | ||||||
|             let entry = file_table.get_entry_mut(fd)?; |             let entry = file_table.get_entry_mut(fd)?; | ||||||
|             entry.set_close_on_spawn((fd_flags & libc::FD_CLOEXEC as u32) != 0); |             entry.set_close_on_spawn((*fd_flags & libc::FD_CLOEXEC as u32) != 0); | ||||||
|             0 |             0 | ||||||
|         } |         } | ||||||
|         FcntlCmd::GetFl() => { |         FcntlCmd::GetFl() => { | ||||||
| @ -74,6 +92,22 @@ pub fn do_fcntl(fd: FileDesc, cmd: &FcntlCmd) -> Result<isize> { | |||||||
|             file.set_status_flags(status_flags)?; |             file.set_status_flags(status_flags)?; | ||||||
|             0 |             0 | ||||||
|         } |         } | ||||||
|  |         FcntlCmd::GetLk(flock_mut_c) => { | ||||||
|  |             let file = file_table.get(fd)?; | ||||||
|  |             let mut lock = Flock::from_c(*flock_mut_c)?; | ||||||
|  |             if let FlockType::F_UNLCK = lock.l_type { | ||||||
|  |                 return_errno!(EINVAL, "invalid flock type for getlk"); | ||||||
|  |             } | ||||||
|  |             file.test_advisory_lock(&mut lock)?; | ||||||
|  |             (*flock_mut_c).copy_from_safe(&lock); | ||||||
|  |             0 | ||||||
|  |         } | ||||||
|  |         FcntlCmd::SetLk(flock_c) => { | ||||||
|  |             let file = file_table.get(fd)?; | ||||||
|  |             let lock = Flock::from_c(*flock_c)?; | ||||||
|  |             file.set_advisory_lock(&lock)?; | ||||||
|  |             0 | ||||||
|  |         } | ||||||
|     }; |     }; | ||||||
|     Ok(ret) |     Ok(ret) | ||||||
| } | } | ||||||
|  | |||||||
							
								
								
									
										88
									
								
								src/libos/src/fs/file_ops/flock.rs
									
									
									
									
									
										Normal file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										88
									
								
								src/libos/src/fs/file_ops/flock.rs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,88 @@ | |||||||
|  | /// File POSIX advisory lock
 | ||||||
|  | use super::*; | ||||||
|  | use process::pid_t; | ||||||
|  | 
 | ||||||
|  | /// C struct for a lock
 | ||||||
|  | #[repr(C)] | ||||||
|  | #[derive(Debug, Copy, Clone)] | ||||||
|  | pub struct flock { | ||||||
|  |     pub l_type: u16, | ||||||
|  |     pub l_whence: u16, | ||||||
|  |     pub l_start: off_t, | ||||||
|  |     pub l_len: off_t, | ||||||
|  |     pub l_pid: pid_t, | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | impl flock { | ||||||
|  |     pub fn copy_from_safe(&mut self, lock: &Flock) { | ||||||
|  |         self.l_type = lock.l_type as u16; | ||||||
|  |         self.l_whence = lock.l_whence as u16; | ||||||
|  |         self.l_start = lock.l_start; | ||||||
|  |         self.l_len = lock.l_len; | ||||||
|  |         self.l_pid = lock.l_pid; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /// Type safe representation of flock
 | ||||||
|  | #[derive(Debug, Copy, Clone)] | ||||||
|  | pub struct Flock { | ||||||
|  |     pub l_type: FlockType, | ||||||
|  |     pub l_whence: FlockWhence, | ||||||
|  |     pub l_start: off_t, | ||||||
|  |     pub l_len: off_t, | ||||||
|  |     pub l_pid: pid_t, | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | impl Flock { | ||||||
|  |     pub fn from_c(flock_c: &flock) -> Result<Self> { | ||||||
|  |         let l_type = FlockType::from_u16(flock_c.l_type)?; | ||||||
|  |         let l_whence = FlockWhence::from_u16(flock_c.l_whence)?; | ||||||
|  |         Ok(Self { | ||||||
|  |             l_type: l_type, | ||||||
|  |             l_whence: l_whence, | ||||||
|  |             l_start: flock_c.l_start, | ||||||
|  |             l_len: flock_c.l_len, | ||||||
|  |             l_pid: flock_c.l_pid, | ||||||
|  |         }) | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #[allow(non_camel_case_types)] | ||||||
|  | #[derive(Debug, Copy, Clone)] | ||||||
|  | #[repr(u16)] | ||||||
|  | pub enum FlockType { | ||||||
|  |     F_RDLCK = 0, | ||||||
|  |     F_WRLCK = 1, | ||||||
|  |     F_UNLCK = 2, | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | impl FlockType { | ||||||
|  |     pub fn from_u16(_type: u16) -> Result<Self> { | ||||||
|  |         Ok(match _type { | ||||||
|  |             0 => FlockType::F_RDLCK, | ||||||
|  |             1 => FlockType::F_WRLCK, | ||||||
|  |             2 => FlockType::F_UNLCK, | ||||||
|  |             _ => return_errno!(EINVAL, "invalid flock type"), | ||||||
|  |         }) | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #[allow(non_camel_case_types)] | ||||||
|  | #[derive(Debug, Copy, Clone)] | ||||||
|  | #[repr(u16)] | ||||||
|  | pub enum FlockWhence { | ||||||
|  |     SEEK_SET = 0, | ||||||
|  |     SEEK_CUR = 1, | ||||||
|  |     SEEK_END = 2, | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | impl FlockWhence { | ||||||
|  |     pub fn from_u16(whence: u16) -> Result<Self> { | ||||||
|  |         Ok(match whence { | ||||||
|  |             0 => FlockWhence::SEEK_SET, | ||||||
|  |             1 => FlockWhence::SEEK_CUR, | ||||||
|  |             2 => FlockWhence::SEEK_END, | ||||||
|  |             _ => return_errno!(EINVAL, "Invalid whence"), | ||||||
|  |         }) | ||||||
|  |     } | ||||||
|  | } | ||||||
| @ -11,6 +11,7 @@ pub use self::dirent::do_getdents64; | |||||||
| pub use self::dup::{do_dup, do_dup2, do_dup3}; | pub use self::dup::{do_dup, do_dup2, do_dup3}; | ||||||
| pub use self::fcntl::{do_fcntl, FcntlCmd}; | pub use self::fcntl::{do_fcntl, FcntlCmd}; | ||||||
| pub use self::file_flags::{AccessMode, CreationFlags, StatusFlags}; | pub use self::file_flags::{AccessMode, CreationFlags, StatusFlags}; | ||||||
|  | pub use self::flock::{Flock, FlockType}; | ||||||
| pub use self::fsync::{do_fdatasync, do_fsync}; | pub use self::fsync::{do_fdatasync, do_fsync}; | ||||||
| pub use self::ioctl::{do_ioctl, IoctlCmd, StructuredIoctlArgType, StructuredIoctlNum}; | pub use self::ioctl::{do_ioctl, IoctlCmd, StructuredIoctlArgType, StructuredIoctlNum}; | ||||||
| pub use self::link::do_link; | pub use self::link::do_link; | ||||||
| @ -34,6 +35,7 @@ mod dirent; | |||||||
| mod dup; | mod dup; | ||||||
| mod fcntl; | mod fcntl; | ||||||
| mod file_flags; | mod file_flags; | ||||||
|  | mod flock; | ||||||
| mod fsync; | mod fsync; | ||||||
| mod ioctl; | mod ioctl; | ||||||
| mod link; | mod link; | ||||||
|  | |||||||
| @ -166,6 +166,32 @@ impl File for INodeFile { | |||||||
|         Ok(()) |         Ok(()) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     fn test_advisory_lock(&self, lock: &mut Flock) -> Result<()> { | ||||||
|  |         // Let the advisory lock could be placed
 | ||||||
|  |         // TODO: Implement the real advisory lock
 | ||||||
|  |         lock.l_type = FlockType::F_UNLCK; | ||||||
|  |         Ok(()) | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     fn set_advisory_lock(&self, lock: &Flock) -> Result<()> { | ||||||
|  |         match lock.l_type { | ||||||
|  |             FlockType::F_RDLCK => { | ||||||
|  |                 if !self.access_mode.readable() { | ||||||
|  |                     return_errno!(EBADF, "File not readable"); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |             FlockType::F_WRLCK => { | ||||||
|  |                 if !self.access_mode.writable() { | ||||||
|  |                     return_errno!(EBADF, "File not writable"); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |             _ => (), | ||||||
|  |         } | ||||||
|  |         // Let the advisory lock could be acquired or released
 | ||||||
|  |         // TODO: Implement the real advisory lock
 | ||||||
|  |         Ok(()) | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     fn as_any(&self) -> &dyn Any { |     fn as_any(&self) -> &dyn Any { | ||||||
|         self |         self | ||||||
|     } |     } | ||||||
|  | |||||||
| @ -10,6 +10,7 @@ use std::mem::MaybeUninit; | |||||||
| 
 | 
 | ||||||
| pub use self::file::{File, FileRef}; | pub use self::file::{File, FileRef}; | ||||||
| pub use self::file_ops::{AccessMode, CreationFlags, Stat, StatusFlags}; | pub use self::file_ops::{AccessMode, CreationFlags, Stat, StatusFlags}; | ||||||
|  | pub use self::file_ops::{Flock, FlockType}; | ||||||
| pub use self::file_ops::{IoctlCmd, StructuredIoctlArgType, StructuredIoctlNum}; | pub use self::file_ops::{IoctlCmd, StructuredIoctlArgType, StructuredIoctlNum}; | ||||||
| pub use self::file_table::{FileDesc, FileTable}; | pub use self::file_table::{FileDesc, FileTable}; | ||||||
| pub use self::inode_file::{AsINodeFile, INodeExt, INodeFile}; | pub use self::inode_file::{AsINodeFile, INodeExt, INodeFile}; | ||||||
|  | |||||||
| @ -347,8 +347,8 @@ pub fn do_sendfile( | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| pub fn do_fcntl(fd: FileDesc, cmd: u32, arg: u64) -> Result<isize> { | pub fn do_fcntl(fd: FileDesc, cmd: u32, arg: u64) -> Result<isize> { | ||||||
|     let cmd = FcntlCmd::from_raw(cmd, arg)?; |     let mut cmd = FcntlCmd::from_raw(cmd, arg)?; | ||||||
|     file_ops::do_fcntl(fd, &cmd) |     file_ops::do_fcntl(fd, &mut cmd) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| pub fn do_ioctl(fd: FileDesc, cmd: u32, argp: *mut u8) -> Result<isize> { | pub fn do_ioctl(fd: FileDesc, cmd: u32, argp: *mut u8) -> Result<isize> { | ||||||
|  | |||||||
| @ -43,6 +43,32 @@ static int __fcntl_setfl(int fd, int open_flags) { | |||||||
|     return 0; |     return 0; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | static int __fcntl_getlk_and_setlk(int fd, int open_flags) { | ||||||
|  |     int ret; | ||||||
|  |     struct flock fl = { F_WRLCK, SEEK_SET, 0, 0, 0 }; | ||||||
|  | 
 | ||||||
|  |     // getlk
 | ||||||
|  |     ret = fcntl(fd, F_GETLK, &fl); | ||||||
|  |     if (ret < 0) { | ||||||
|  |         THROW_ERROR("failed to call getlk"); | ||||||
|  |     } | ||||||
|  |     if (fl.l_type != F_UNLCK) { | ||||||
|  |         THROW_ERROR("failed to get correct fl type"); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     // setlk
 | ||||||
|  |     if ((open_flags & O_WRONLY) || (open_flags & O_RDWR)) | ||||||
|  |         fl.l_type = F_WRLCK; | ||||||
|  |     else | ||||||
|  |         fl.l_type = F_RDLCK; | ||||||
|  |     ret = fcntl(fd, F_SETLK, &fl); | ||||||
|  |     if (ret < 0) { | ||||||
|  |         THROW_ERROR("failed to call setlk"); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     return 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| typedef int(*test_fcntl_func_t)(int fd, int open_flags); | typedef int(*test_fcntl_func_t)(int fd, int open_flags); | ||||||
| 
 | 
 | ||||||
| static int test_fcntl_framework(test_fcntl_func_t fn) { | static int test_fcntl_framework(test_fcntl_func_t fn) { | ||||||
| @ -74,6 +100,10 @@ static int test_fcntl_setfl() { | |||||||
|     return test_fcntl_framework(__fcntl_setfl); |     return test_fcntl_framework(__fcntl_setfl); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | static int test_getlk_and_setlk() { | ||||||
|  |     return test_fcntl_framework(__fcntl_getlk_and_setlk); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| // ============================================================================
 | // ============================================================================
 | ||||||
| // Test suite
 | // Test suite
 | ||||||
| // ============================================================================
 | // ============================================================================
 | ||||||
| @ -81,6 +111,7 @@ static int test_fcntl_setfl() { | |||||||
| static test_case_t test_cases[] = { | static test_case_t test_cases[] = { | ||||||
|     TEST_CASE(test_fcntl_getfl), |     TEST_CASE(test_fcntl_getfl), | ||||||
|     TEST_CASE(test_fcntl_setfl), |     TEST_CASE(test_fcntl_setfl), | ||||||
|  |     TEST_CASE(test_getlk_and_setlk), | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| int main() { | int main() { | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user