Skip to content

Commit 49d4ada

Browse files
committed
Define a file descriptor reservation/commit/rollback abstraction.
Signed-off-by: Wedson Almeida Filho <wedsonaf@google.com>
1 parent 739c1fb commit 49d4ada

File tree

1 file changed

+46
-0
lines changed

1 file changed

+46
-0
lines changed

rust/kernel/file.rs

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,3 +82,49 @@ impl Deref for FileRef {
8282
self.0.deref()
8383
}
8484
}
85+
86+
/// A file descriptor reservation.
87+
///
88+
/// This allows the creation of a file descriptor in two steps: first, we reserve a slot for it,
89+
/// then we commit or drop the reservation. The first step may fail (e.g., the current process ran
90+
/// out of available slots), but commit and drop never fail (and are mutually exclusive).
91+
pub struct FileDescriptorReservation {
92+
fd: u32,
93+
}
94+
95+
impl FileDescriptorReservation {
96+
/// Creates a new file descriptor reservation.
97+
pub fn new(flags: u32) -> Result<Self> {
98+
let fd = unsafe { bindings::get_unused_fd_flags(flags) };
99+
if fd < 0 {
100+
return Err(Error::from_kernel_errno(fd));
101+
}
102+
Ok(Self { fd: fd as _ })
103+
}
104+
105+
/// Returns the file descriptor number that was reserved.
106+
pub fn reserved_fd(&self) -> u32 {
107+
self.fd
108+
}
109+
110+
/// Commits the reservation.
111+
///
112+
/// The previously reserved file descriptor is bound to `file`.
113+
pub fn commit(self, file: File) {
114+
// SAFETY: `self.fd` was previously returned by `get_unused_fd_flags`, and `file.ptr` is
115+
// guaranteed to have an owned ref count by its type invariants.
116+
unsafe { bindings::fd_install(self.fd, file.ptr) };
117+
118+
// `fd_install` consumes both the file descriptor and the file reference, so we cannot run
119+
// the destructors.
120+
core::mem::forget(self);
121+
core::mem::forget(file);
122+
}
123+
}
124+
125+
impl Drop for FileDescriptorReservation {
126+
fn drop(&mut self) {
127+
// SAFETY: `self.fd` was returned by a previous call to `get_unused_fd_flags`.
128+
unsafe { bindings::put_unused_fd(self.fd) };
129+
}
130+
}

0 commit comments

Comments
 (0)