1 // SPDX-License-Identifier: GPL-2.0 2 3 // Copyright (C) 2024 Google LLC. 4 5 //! Files and file descriptors. 6 //! 7 //! C headers: [`include/linux/fs.h`](srctree/include/linux/fs.h) and 8 //! [`include/linux/file.h`](srctree/include/linux/file.h) 9 10 use crate::{ 11 bindings, 12 error::{code::*, Error, Result}, 13 types::{ARef, AlwaysRefCounted, Opaque}, 14 }; 15 use core::ptr; 16 17 /// Flags associated with a [`File`]. 18 pub mod flags { 19 /// File is opened in append mode. 20 pub const O_APPEND: u32 = bindings::O_APPEND; 21 22 /// Signal-driven I/O is enabled. 23 pub const O_ASYNC: u32 = bindings::FASYNC; 24 25 /// Close-on-exec flag is set. 26 pub const O_CLOEXEC: u32 = bindings::O_CLOEXEC; 27 28 /// File was created if it didn't already exist. 29 pub const O_CREAT: u32 = bindings::O_CREAT; 30 31 /// Direct I/O is enabled for this file. 32 pub const O_DIRECT: u32 = bindings::O_DIRECT; 33 34 /// File must be a directory. 35 pub const O_DIRECTORY: u32 = bindings::O_DIRECTORY; 36 37 /// Like [`O_SYNC`] except metadata is not synced. 38 pub const O_DSYNC: u32 = bindings::O_DSYNC; 39 40 /// Ensure that this file is created with the `open(2)` call. 41 pub const O_EXCL: u32 = bindings::O_EXCL; 42 43 /// Large file size enabled (`off64_t` over `off_t`). 44 pub const O_LARGEFILE: u32 = bindings::O_LARGEFILE; 45 46 /// Do not update the file last access time. 47 pub const O_NOATIME: u32 = bindings::O_NOATIME; 48 49 /// File should not be used as process's controlling terminal. 50 pub const O_NOCTTY: u32 = bindings::O_NOCTTY; 51 52 /// If basename of path is a symbolic link, fail open. 53 pub const O_NOFOLLOW: u32 = bindings::O_NOFOLLOW; 54 55 /// File is using nonblocking I/O. 56 pub const O_NONBLOCK: u32 = bindings::O_NONBLOCK; 57 58 /// File is using nonblocking I/O. 59 /// 60 /// This is effectively the same flag as [`O_NONBLOCK`] on all architectures 61 /// except SPARC64. 62 pub const O_NDELAY: u32 = bindings::O_NDELAY; 63 64 /// Used to obtain a path file descriptor. 65 pub const O_PATH: u32 = bindings::O_PATH; 66 67 /// Write operations on this file will flush data and metadata. 68 pub const O_SYNC: u32 = bindings::O_SYNC; 69 70 /// This file is an unnamed temporary regular file. 71 pub const O_TMPFILE: u32 = bindings::O_TMPFILE; 72 73 /// File should be truncated to length 0. 74 pub const O_TRUNC: u32 = bindings::O_TRUNC; 75 76 /// Bitmask for access mode flags. 77 /// 78 /// # Examples 79 /// 80 /// ``` 81 /// use kernel::fs::file; 82 /// # fn do_something() {} 83 /// # let flags = 0; 84 /// if (flags & file::flags::O_ACCMODE) == file::flags::O_RDONLY { 85 /// do_something(); 86 /// } 87 /// ``` 88 pub const O_ACCMODE: u32 = bindings::O_ACCMODE; 89 90 /// File is read only. 91 pub const O_RDONLY: u32 = bindings::O_RDONLY; 92 93 /// File is write only. 94 pub const O_WRONLY: u32 = bindings::O_WRONLY; 95 96 /// File can be both read and written. 97 pub const O_RDWR: u32 = bindings::O_RDWR; 98 } 99 100 /// Wraps the kernel's `struct file`. Thread safe. 101 /// 102 /// This represents an open file rather than a file on a filesystem. Processes generally reference 103 /// open files using file descriptors. However, file descriptors are not the same as files. A file 104 /// descriptor is just an integer that corresponds to a file, and a single file may be referenced 105 /// by multiple file descriptors. 106 /// 107 /// # Refcounting 108 /// 109 /// Instances of this type are reference-counted. The reference count is incremented by the 110 /// `fget`/`get_file` functions and decremented by `fput`. The Rust type `ARef<File>` represents a 111 /// pointer that owns a reference count on the file. 112 /// 113 /// Whenever a process opens a file descriptor (fd), it stores a pointer to the file in its fd 114 /// table (`struct files_struct`). This pointer owns a reference count to the file, ensuring the 115 /// file isn't prematurely deleted while the file descriptor is open. In Rust terminology, the 116 /// pointers in `struct files_struct` are `ARef<File>` pointers. 117 /// 118 /// ## Light refcounts 119 /// 120 /// Whenever a process has an fd to a file, it may use something called a "light refcount" as a 121 /// performance optimization. Light refcounts are acquired by calling `fdget` and released with 122 /// `fdput`. The idea behind light refcounts is that if the fd is not closed between the calls to 123 /// `fdget` and `fdput`, then the refcount cannot hit zero during that time, as the `struct 124 /// files_struct` holds a reference until the fd is closed. This means that it's safe to access the 125 /// file even if `fdget` does not increment the refcount. 126 /// 127 /// The requirement that the fd is not closed during a light refcount applies globally across all 128 /// threads - not just on the thread using the light refcount. For this reason, light refcounts are 129 /// only used when the `struct files_struct` is not shared with other threads, since this ensures 130 /// that other unrelated threads cannot suddenly start using the fd and close it. Therefore, 131 /// calling `fdget` on a shared `struct files_struct` creates a normal refcount instead of a light 132 /// refcount. 133 /// 134 /// Light reference counts must be released with `fdput` before the system call returns to 135 /// userspace. This means that if you wait until the current system call returns to userspace, then 136 /// all light refcounts that existed at the time have gone away. 137 /// 138 /// ### The file position 139 /// 140 /// Each `struct file` has a position integer, which is protected by the `f_pos_lock` mutex. 141 /// However, if the `struct file` is not shared, then the kernel may avoid taking the lock as a 142 /// performance optimization. 143 /// 144 /// The condition for avoiding the `f_pos_lock` mutex is different from the condition for using 145 /// `fdget`. With `fdget`, you may avoid incrementing the refcount as long as the current fd table 146 /// is not shared; it is okay if there are other fd tables that also reference the same `struct 147 /// file`. However, `fdget_pos` can only avoid taking the `f_pos_lock` if the entire `struct file` 148 /// is not shared, as different processes with an fd to the same `struct file` share the same 149 /// position. 150 /// 151 /// To represent files that are not thread safe due to this optimization, the [`LocalFile`] type is 152 /// used. 153 /// 154 /// ## Rust references 155 /// 156 /// The reference type `&File` is similar to light refcounts: 157 /// 158 /// * `&File` references don't own a reference count. They can only exist as long as the reference 159 /// count stays positive, and can only be created when there is some mechanism in place to ensure 160 /// this. 161 /// 162 /// * The Rust borrow-checker normally ensures this by enforcing that the `ARef<File>` from which 163 /// a `&File` is created outlives the `&File`. 164 /// 165 /// * Using the unsafe [`File::from_raw_file`] means that it is up to the caller to ensure that the 166 /// `&File` only exists while the reference count is positive. 167 /// 168 /// * You can think of `fdget` as using an fd to look up an `ARef<File>` in the `struct 169 /// files_struct` and create an `&File` from it. The "fd cannot be closed" rule is like the Rust 170 /// rule "the `ARef<File>` must outlive the `&File`". 171 /// 172 /// # Invariants 173 /// 174 /// * All instances of this type are refcounted using the `f_count` field. 175 /// * There must not be any active calls to `fdget_pos` on this file that did not take the 176 /// `f_pos_lock` mutex. 177 #[repr(transparent)] 178 pub struct File { 179 inner: Opaque<bindings::file>, 180 } 181 182 // SAFETY: This file is known to not have any active `fdget_pos` calls that did not take the 183 // `f_pos_lock` mutex, so it is safe to transfer it between threads. 184 unsafe impl Send for File {} 185 186 // SAFETY: This file is known to not have any active `fdget_pos` calls that did not take the 187 // `f_pos_lock` mutex, so it is safe to access its methods from several threads in parallel. 188 unsafe impl Sync for File {} 189 190 // SAFETY: The type invariants guarantee that `File` is always ref-counted. This implementation 191 // makes `ARef<File>` own a normal refcount. 192 unsafe impl AlwaysRefCounted for File { 193 #[inline] 194 fn inc_ref(&self) { 195 // SAFETY: The existence of a shared reference means that the refcount is nonzero. 196 unsafe { bindings::get_file(self.as_ptr()) }; 197 } 198 199 #[inline] 200 unsafe fn dec_ref(obj: ptr::NonNull<File>) { 201 // SAFETY: To call this method, the caller passes us ownership of a normal refcount, so we 202 // may drop it. The cast is okay since `File` has the same representation as `struct file`. 203 unsafe { bindings::fput(obj.cast().as_ptr()) } 204 } 205 } 206 207 /// Wraps the kernel's `struct file`. Not thread safe. 208 /// 209 /// This type represents a file that is not known to be safe to transfer across thread boundaries. 210 /// To obtain a thread-safe [`File`], use the [`assume_no_fdget_pos`] conversion. 211 /// 212 /// See the documentation for [`File`] for more information. 213 /// 214 /// # Invariants 215 /// 216 /// * All instances of this type are refcounted using the `f_count` field. 217 /// * If there is an active call to `fdget_pos` that did not take the `f_pos_lock` mutex, then it 218 /// must be on the same thread as this file. 219 /// 220 /// [`assume_no_fdget_pos`]: LocalFile::assume_no_fdget_pos 221 pub struct LocalFile { 222 inner: Opaque<bindings::file>, 223 } 224 225 // SAFETY: The type invariants guarantee that `LocalFile` is always ref-counted. This implementation 226 // makes `ARef<File>` own a normal refcount. 227 unsafe impl AlwaysRefCounted for LocalFile { 228 #[inline] 229 fn inc_ref(&self) { 230 // SAFETY: The existence of a shared reference means that the refcount is nonzero. 231 unsafe { bindings::get_file(self.as_ptr()) }; 232 } 233 234 #[inline] 235 unsafe fn dec_ref(obj: ptr::NonNull<LocalFile>) { 236 // SAFETY: To call this method, the caller passes us ownership of a normal refcount, so we 237 // may drop it. The cast is okay since `File` has the same representation as `struct file`. 238 unsafe { bindings::fput(obj.cast().as_ptr()) } 239 } 240 } 241 242 impl LocalFile { 243 /// Constructs a new `struct file` wrapper from a file descriptor. 244 /// 245 /// The file descriptor belongs to the current process, and there might be active local calls 246 /// to `fdget_pos` on the same file. 247 /// 248 /// To obtain an `ARef<File>`, use the [`assume_no_fdget_pos`] function to convert. 249 /// 250 /// [`assume_no_fdget_pos`]: LocalFile::assume_no_fdget_pos 251 #[inline] 252 pub fn fget(fd: u32) -> Result<ARef<LocalFile>, BadFdError> { 253 // SAFETY: FFI call, there are no requirements on `fd`. 254 let ptr = ptr::NonNull::new(unsafe { bindings::fget(fd) }).ok_or(BadFdError)?; 255 256 // SAFETY: `bindings::fget` created a refcount, and we pass ownership of it to the `ARef`. 257 // 258 // INVARIANT: This file is in the fd table on this thread, so either all `fdget_pos` calls 259 // are on this thread, or the file is shared, in which case `fdget_pos` calls took the 260 // `f_pos_lock` mutex. 261 Ok(unsafe { ARef::from_raw(ptr.cast()) }) 262 } 263 264 /// Creates a reference to a [`LocalFile`] from a valid pointer. 265 /// 266 /// # Safety 267 /// 268 /// * The caller must ensure that `ptr` points at a valid file and that the file's refcount is 269 /// positive for the duration of 'a. 270 /// * The caller must ensure that if there is an active call to `fdget_pos` that did not take 271 /// the `f_pos_lock` mutex, then that call is on the current thread. 272 #[inline] 273 pub unsafe fn from_raw_file<'a>(ptr: *const bindings::file) -> &'a LocalFile { 274 // SAFETY: The caller guarantees that the pointer is not dangling and stays valid for the 275 // duration of 'a. The cast is okay because `File` is `repr(transparent)`. 276 // 277 // INVARIANT: The caller guarantees that there are no problematic `fdget_pos` calls. 278 unsafe { &*ptr.cast() } 279 } 280 281 /// Assume that there are no active `fdget_pos` calls that prevent us from sharing this file. 282 /// 283 /// This makes it safe to transfer this file to other threads. No checks are performed, and 284 /// using it incorrectly may lead to a data race on the file position if the file is shared 285 /// with another thread. 286 /// 287 /// This method is intended to be used together with [`LocalFile::fget`] when the caller knows 288 /// statically that there are no `fdget_pos` calls on the current thread. For example, you 289 /// might use it when calling `fget` from an ioctl, since ioctls usually do not touch the file 290 /// position. 291 /// 292 /// # Safety 293 /// 294 /// There must not be any active `fdget_pos` calls on the current thread. 295 #[inline] 296 pub unsafe fn assume_no_fdget_pos(me: ARef<LocalFile>) -> ARef<File> { 297 // INVARIANT: There are no `fdget_pos` calls on the current thread, and by the type 298 // invariants, if there is a `fdget_pos` call on another thread, then it took the 299 // `f_pos_lock` mutex. 300 // 301 // SAFETY: `LocalFile` and `File` have the same layout. 302 unsafe { ARef::from_raw(ARef::into_raw(me).cast()) } 303 } 304 305 /// Returns a raw pointer to the inner C struct. 306 #[inline] 307 pub fn as_ptr(&self) -> *mut bindings::file { 308 self.inner.get() 309 } 310 311 /// Returns the flags associated with the file. 312 /// 313 /// The flags are a combination of the constants in [`flags`]. 314 #[inline] 315 pub fn flags(&self) -> u32 { 316 // This `read_volatile` is intended to correspond to a READ_ONCE call. 317 // 318 // SAFETY: The file is valid because the shared reference guarantees a nonzero refcount. 319 // 320 // FIXME(read_once): Replace with `read_once` when available on the Rust side. 321 unsafe { core::ptr::addr_of!((*self.as_ptr()).f_flags).read_volatile() } 322 } 323 } 324 325 impl File { 326 /// Creates a reference to a [`File`] from a valid pointer. 327 /// 328 /// # Safety 329 /// 330 /// * The caller must ensure that `ptr` points at a valid file and that the file's refcount is 331 /// positive for the duration of 'a. 332 /// * The caller must ensure that if there are active `fdget_pos` calls on this file, then they 333 /// took the `f_pos_lock` mutex. 334 #[inline] 335 pub unsafe fn from_raw_file<'a>(ptr: *const bindings::file) -> &'a File { 336 // SAFETY: The caller guarantees that the pointer is not dangling and stays valid for the 337 // duration of 'a. The cast is okay because `File` is `repr(transparent)`. 338 // 339 // INVARIANT: The caller guarantees that there are no problematic `fdget_pos` calls. 340 unsafe { &*ptr.cast() } 341 } 342 } 343 344 // Make LocalFile methods available on File. 345 impl core::ops::Deref for File { 346 type Target = LocalFile; 347 #[inline] 348 fn deref(&self) -> &LocalFile { 349 // SAFETY: The caller provides a `&File`, and since it is a reference, it must point at a 350 // valid file for the desired duration. 351 // 352 // By the type invariants, there are no `fdget_pos` calls that did not take the 353 // `f_pos_lock` mutex. 354 unsafe { LocalFile::from_raw_file(self as *const File as *const bindings::file) } 355 } 356 } 357 358 /// Represents the `EBADF` error code. 359 /// 360 /// Used for methods that can only fail with `EBADF`. 361 #[derive(Copy, Clone, Eq, PartialEq)] 362 pub struct BadFdError; 363 364 impl From<BadFdError> for Error { 365 #[inline] 366 fn from(_: BadFdError) -> Error { 367 EBADF 368 } 369 } 370 371 impl core::fmt::Debug for BadFdError { 372 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { 373 f.pad("EBADF") 374 } 375 } 376