Hans de Goede | 0fd1695 | 2019-12-12 15:09:14 +0100 | [diff] [blame] | 1 | // SPDX-License-Identifier: MIT |
| 2 | /* |
| 3 | * VirtualBox Guest Shared Folders support: Regular file inode and file ops. |
| 4 | * |
| 5 | * Copyright (C) 2006-2018 Oracle Corporation |
| 6 | */ |
| 7 | |
| 8 | #include <linux/mm.h> |
| 9 | #include <linux/page-flags.h> |
| 10 | #include <linux/pagemap.h> |
| 11 | #include <linux/highmem.h> |
| 12 | #include <linux/sizes.h> |
| 13 | #include "vfsmod.h" |
| 14 | |
| 15 | struct vboxsf_handle { |
| 16 | u64 handle; |
| 17 | u32 root; |
| 18 | u32 access_flags; |
| 19 | struct kref refcount; |
| 20 | struct list_head head; |
| 21 | }; |
| 22 | |
Hans de Goede | 02f840f | 2021-01-21 10:55:03 +0100 | [diff] [blame] | 23 | struct vboxsf_handle *vboxsf_create_sf_handle(struct inode *inode, |
| 24 | u64 handle, u32 access_flags) |
Hans de Goede | 0fd1695 | 2019-12-12 15:09:14 +0100 | [diff] [blame] | 25 | { |
| 26 | struct vboxsf_inode *sf_i = VBOXSF_I(inode); |
Hans de Goede | 02f840f | 2021-01-21 10:55:03 +0100 | [diff] [blame] | 27 | struct vboxsf_handle *sf_handle; |
| 28 | |
| 29 | sf_handle = kmalloc(sizeof(*sf_handle), GFP_KERNEL); |
| 30 | if (!sf_handle) |
| 31 | return ERR_PTR(-ENOMEM); |
| 32 | |
| 33 | /* the host may have given us different attr then requested */ |
| 34 | sf_i->force_restat = 1; |
| 35 | |
| 36 | /* init our handle struct and add it to the inode's handles list */ |
| 37 | sf_handle->handle = handle; |
| 38 | sf_handle->root = VBOXSF_SBI(inode->i_sb)->root; |
| 39 | sf_handle->access_flags = access_flags; |
| 40 | kref_init(&sf_handle->refcount); |
| 41 | |
| 42 | mutex_lock(&sf_i->handle_list_mutex); |
| 43 | list_add(&sf_handle->head, &sf_i->handle_list); |
| 44 | mutex_unlock(&sf_i->handle_list_mutex); |
| 45 | |
| 46 | return sf_handle; |
| 47 | } |
| 48 | |
| 49 | static int vboxsf_file_open(struct inode *inode, struct file *file) |
| 50 | { |
| 51 | struct vboxsf_sbi *sbi = VBOXSF_SBI(inode->i_sb); |
Hans de Goede | 0fd1695 | 2019-12-12 15:09:14 +0100 | [diff] [blame] | 52 | struct shfl_createparms params = {}; |
| 53 | struct vboxsf_handle *sf_handle; |
| 54 | u32 access_flags = 0; |
| 55 | int err; |
| 56 | |
Hans de Goede | 0fd1695 | 2019-12-12 15:09:14 +0100 | [diff] [blame] | 57 | /* |
| 58 | * We check the value of params.handle afterwards to find out if |
| 59 | * the call succeeded or failed, as the API does not seem to cleanly |
| 60 | * distinguish error and informational messages. |
| 61 | * |
| 62 | * Furthermore, we must set params.handle to SHFL_HANDLE_NIL to |
| 63 | * make the shared folders host service use our mode parameter. |
| 64 | */ |
| 65 | params.handle = SHFL_HANDLE_NIL; |
| 66 | if (file->f_flags & O_CREAT) { |
| 67 | params.create_flags |= SHFL_CF_ACT_CREATE_IF_NEW; |
| 68 | /* |
| 69 | * We ignore O_EXCL, as the Linux kernel seems to call create |
| 70 | * beforehand itself, so O_EXCL should always fail. |
| 71 | */ |
| 72 | if (file->f_flags & O_TRUNC) |
| 73 | params.create_flags |= SHFL_CF_ACT_OVERWRITE_IF_EXISTS; |
| 74 | else |
| 75 | params.create_flags |= SHFL_CF_ACT_OPEN_IF_EXISTS; |
| 76 | } else { |
| 77 | params.create_flags |= SHFL_CF_ACT_FAIL_IF_NEW; |
| 78 | if (file->f_flags & O_TRUNC) |
| 79 | params.create_flags |= SHFL_CF_ACT_OVERWRITE_IF_EXISTS; |
| 80 | } |
| 81 | |
| 82 | switch (file->f_flags & O_ACCMODE) { |
| 83 | case O_RDONLY: |
| 84 | access_flags |= SHFL_CF_ACCESS_READ; |
| 85 | break; |
| 86 | |
| 87 | case O_WRONLY: |
| 88 | access_flags |= SHFL_CF_ACCESS_WRITE; |
| 89 | break; |
| 90 | |
| 91 | case O_RDWR: |
| 92 | access_flags |= SHFL_CF_ACCESS_READWRITE; |
| 93 | break; |
| 94 | |
| 95 | default: |
| 96 | WARN_ON(1); |
| 97 | } |
| 98 | |
| 99 | if (file->f_flags & O_APPEND) |
| 100 | access_flags |= SHFL_CF_ACCESS_APPEND; |
| 101 | |
| 102 | params.create_flags |= access_flags; |
| 103 | params.info.attr.mode = inode->i_mode; |
| 104 | |
| 105 | err = vboxsf_create_at_dentry(file_dentry(file), ¶ms); |
| 106 | if (err == 0 && params.handle == SHFL_HANDLE_NIL) |
| 107 | err = (params.result == SHFL_FILE_EXISTS) ? -EEXIST : -ENOENT; |
Hans de Goede | 02f840f | 2021-01-21 10:55:03 +0100 | [diff] [blame] | 108 | if (err) |
Hans de Goede | 0fd1695 | 2019-12-12 15:09:14 +0100 | [diff] [blame] | 109 | return err; |
Hans de Goede | 02f840f | 2021-01-21 10:55:03 +0100 | [diff] [blame] | 110 | |
| 111 | sf_handle = vboxsf_create_sf_handle(inode, params.handle, access_flags); |
| 112 | if (IS_ERR(sf_handle)) { |
| 113 | vboxsf_close(sbi->root, params.handle); |
| 114 | return PTR_ERR(sf_handle); |
Hans de Goede | 0fd1695 | 2019-12-12 15:09:14 +0100 | [diff] [blame] | 115 | } |
| 116 | |
Hans de Goede | 0fd1695 | 2019-12-12 15:09:14 +0100 | [diff] [blame] | 117 | file->private_data = sf_handle; |
| 118 | return 0; |
| 119 | } |
| 120 | |
| 121 | static void vboxsf_handle_release(struct kref *refcount) |
| 122 | { |
| 123 | struct vboxsf_handle *sf_handle = |
| 124 | container_of(refcount, struct vboxsf_handle, refcount); |
| 125 | |
| 126 | vboxsf_close(sf_handle->root, sf_handle->handle); |
| 127 | kfree(sf_handle); |
| 128 | } |
| 129 | |
Hans de Goede | 02f840f | 2021-01-21 10:55:03 +0100 | [diff] [blame] | 130 | void vboxsf_release_sf_handle(struct inode *inode, struct vboxsf_handle *sf_handle) |
Hans de Goede | 0fd1695 | 2019-12-12 15:09:14 +0100 | [diff] [blame] | 131 | { |
| 132 | struct vboxsf_inode *sf_i = VBOXSF_I(inode); |
Hans de Goede | 0fd1695 | 2019-12-12 15:09:14 +0100 | [diff] [blame] | 133 | |
| 134 | mutex_lock(&sf_i->handle_list_mutex); |
| 135 | list_del(&sf_handle->head); |
| 136 | mutex_unlock(&sf_i->handle_list_mutex); |
| 137 | |
| 138 | kref_put(&sf_handle->refcount, vboxsf_handle_release); |
Hans de Goede | 02f840f | 2021-01-21 10:55:03 +0100 | [diff] [blame] | 139 | } |
| 140 | |
| 141 | static int vboxsf_file_release(struct inode *inode, struct file *file) |
| 142 | { |
| 143 | /* |
| 144 | * When a file is closed on our (the guest) side, we want any subsequent |
| 145 | * accesses done on the host side to see all changes done from our side. |
| 146 | */ |
| 147 | filemap_write_and_wait(inode->i_mapping); |
| 148 | |
| 149 | vboxsf_release_sf_handle(inode, file->private_data); |
Hans de Goede | 0fd1695 | 2019-12-12 15:09:14 +0100 | [diff] [blame] | 150 | return 0; |
| 151 | } |
| 152 | |
| 153 | /* |
| 154 | * Write back dirty pages now, because there may not be any suitable |
| 155 | * open files later |
| 156 | */ |
| 157 | static void vboxsf_vma_close(struct vm_area_struct *vma) |
| 158 | { |
| 159 | filemap_write_and_wait(vma->vm_file->f_mapping); |
| 160 | } |
| 161 | |
| 162 | static const struct vm_operations_struct vboxsf_file_vm_ops = { |
| 163 | .close = vboxsf_vma_close, |
| 164 | .fault = filemap_fault, |
| 165 | .map_pages = filemap_map_pages, |
| 166 | }; |
| 167 | |
| 168 | static int vboxsf_file_mmap(struct file *file, struct vm_area_struct *vma) |
| 169 | { |
| 170 | int err; |
| 171 | |
| 172 | err = generic_file_mmap(file, vma); |
| 173 | if (!err) |
| 174 | vma->vm_ops = &vboxsf_file_vm_ops; |
| 175 | |
| 176 | return err; |
| 177 | } |
| 178 | |
| 179 | /* |
| 180 | * Note that since we are accessing files on the host's filesystem, files |
| 181 | * may always be changed underneath us by the host! |
| 182 | * |
| 183 | * The vboxsf API between the guest and the host does not offer any functions |
| 184 | * to deal with this. There is no inode-generation to check for changes, no |
| 185 | * events / callback on changes and no way to lock files. |
| 186 | * |
| 187 | * To avoid returning stale data when a file gets *opened* on our (the guest) |
| 188 | * side, we do a "stat" on the host side, then compare the mtime with the |
| 189 | * last known mtime and invalidate the page-cache if they differ. |
| 190 | * This is done from vboxsf_inode_revalidate(). |
| 191 | * |
| 192 | * When reads are done through the read_iter fop, it is possible to do |
| 193 | * further cache revalidation then, there are 3 options to deal with this: |
| 194 | * |
| 195 | * 1) Rely solely on the revalidation done at open time |
| 196 | * 2) Do another "stat" and compare mtime again. Unfortunately the vboxsf |
| 197 | * host API does not allow stat on handles, so we would need to use |
| 198 | * file->f_path.dentry and the stat will then fail if the file was unlinked |
| 199 | * or renamed (and there is no thing like NFS' silly-rename). So we get: |
| 200 | * 2a) "stat" and compare mtime, on stat failure invalidate the cache |
| 201 | * 2b) "stat" and compare mtime, on stat failure do nothing |
| 202 | * 3) Simply always call invalidate_inode_pages2_range on the range of the read |
| 203 | * |
| 204 | * Currently we are keeping things KISS and using option 1. this allows |
| 205 | * directly using generic_file_read_iter without wrapping it. |
| 206 | * |
| 207 | * This means that only data written on the host side before open() on |
| 208 | * the guest side is guaranteed to be seen by the guest. If necessary |
| 209 | * we may provide other read-cache strategies in the future and make this |
| 210 | * configurable through a mount option. |
| 211 | */ |
| 212 | const struct file_operations vboxsf_reg_fops = { |
| 213 | .llseek = generic_file_llseek, |
| 214 | .read_iter = generic_file_read_iter, |
| 215 | .write_iter = generic_file_write_iter, |
| 216 | .mmap = vboxsf_file_mmap, |
| 217 | .open = vboxsf_file_open, |
| 218 | .release = vboxsf_file_release, |
| 219 | .fsync = noop_fsync, |
| 220 | .splice_read = generic_file_splice_read, |
| 221 | }; |
| 222 | |
| 223 | const struct inode_operations vboxsf_reg_iops = { |
| 224 | .getattr = vboxsf_getattr, |
| 225 | .setattr = vboxsf_setattr |
| 226 | }; |
| 227 | |
| 228 | static int vboxsf_readpage(struct file *file, struct page *page) |
| 229 | { |
| 230 | struct vboxsf_handle *sf_handle = file->private_data; |
| 231 | loff_t off = page_offset(page); |
| 232 | u32 nread = PAGE_SIZE; |
| 233 | u8 *buf; |
| 234 | int err; |
| 235 | |
| 236 | buf = kmap(page); |
| 237 | |
| 238 | err = vboxsf_read(sf_handle->root, sf_handle->handle, off, &nread, buf); |
| 239 | if (err == 0) { |
| 240 | memset(&buf[nread], 0, PAGE_SIZE - nread); |
| 241 | flush_dcache_page(page); |
| 242 | SetPageUptodate(page); |
| 243 | } else { |
| 244 | SetPageError(page); |
| 245 | } |
| 246 | |
| 247 | kunmap(page); |
| 248 | unlock_page(page); |
| 249 | return err; |
| 250 | } |
| 251 | |
| 252 | static struct vboxsf_handle *vboxsf_get_write_handle(struct vboxsf_inode *sf_i) |
| 253 | { |
| 254 | struct vboxsf_handle *h, *sf_handle = NULL; |
| 255 | |
| 256 | mutex_lock(&sf_i->handle_list_mutex); |
| 257 | list_for_each_entry(h, &sf_i->handle_list, head) { |
| 258 | if (h->access_flags == SHFL_CF_ACCESS_WRITE || |
| 259 | h->access_flags == SHFL_CF_ACCESS_READWRITE) { |
| 260 | kref_get(&h->refcount); |
| 261 | sf_handle = h; |
| 262 | break; |
| 263 | } |
| 264 | } |
| 265 | mutex_unlock(&sf_i->handle_list_mutex); |
| 266 | |
| 267 | return sf_handle; |
| 268 | } |
| 269 | |
| 270 | static int vboxsf_writepage(struct page *page, struct writeback_control *wbc) |
| 271 | { |
| 272 | struct inode *inode = page->mapping->host; |
| 273 | struct vboxsf_inode *sf_i = VBOXSF_I(inode); |
| 274 | struct vboxsf_handle *sf_handle; |
| 275 | loff_t off = page_offset(page); |
| 276 | loff_t size = i_size_read(inode); |
| 277 | u32 nwrite = PAGE_SIZE; |
| 278 | u8 *buf; |
| 279 | int err; |
| 280 | |
| 281 | if (off + PAGE_SIZE > size) |
| 282 | nwrite = size & ~PAGE_MASK; |
| 283 | |
| 284 | sf_handle = vboxsf_get_write_handle(sf_i); |
| 285 | if (!sf_handle) |
| 286 | return -EBADF; |
| 287 | |
| 288 | buf = kmap(page); |
| 289 | err = vboxsf_write(sf_handle->root, sf_handle->handle, |
| 290 | off, &nwrite, buf); |
| 291 | kunmap(page); |
| 292 | |
| 293 | kref_put(&sf_handle->refcount, vboxsf_handle_release); |
| 294 | |
| 295 | if (err == 0) { |
| 296 | ClearPageError(page); |
| 297 | /* mtime changed */ |
| 298 | sf_i->force_restat = 1; |
| 299 | } else { |
| 300 | ClearPageUptodate(page); |
| 301 | } |
| 302 | |
| 303 | unlock_page(page); |
| 304 | return err; |
| 305 | } |
| 306 | |
| 307 | static int vboxsf_write_end(struct file *file, struct address_space *mapping, |
| 308 | loff_t pos, unsigned int len, unsigned int copied, |
| 309 | struct page *page, void *fsdata) |
| 310 | { |
| 311 | struct inode *inode = mapping->host; |
| 312 | struct vboxsf_handle *sf_handle = file->private_data; |
| 313 | unsigned int from = pos & ~PAGE_MASK; |
| 314 | u32 nwritten = len; |
| 315 | u8 *buf; |
| 316 | int err; |
| 317 | |
| 318 | /* zero the stale part of the page if we did a short copy */ |
| 319 | if (!PageUptodate(page) && copied < len) |
| 320 | zero_user(page, from + copied, len - copied); |
| 321 | |
| 322 | buf = kmap(page); |
| 323 | err = vboxsf_write(sf_handle->root, sf_handle->handle, |
| 324 | pos, &nwritten, buf + from); |
| 325 | kunmap(page); |
| 326 | |
| 327 | if (err) { |
| 328 | nwritten = 0; |
| 329 | goto out; |
| 330 | } |
| 331 | |
| 332 | /* mtime changed */ |
| 333 | VBOXSF_I(inode)->force_restat = 1; |
| 334 | |
| 335 | if (!PageUptodate(page) && nwritten == PAGE_SIZE) |
| 336 | SetPageUptodate(page); |
| 337 | |
| 338 | pos += nwritten; |
| 339 | if (pos > inode->i_size) |
| 340 | i_size_write(inode, pos); |
| 341 | |
| 342 | out: |
| 343 | unlock_page(page); |
| 344 | put_page(page); |
| 345 | |
| 346 | return nwritten; |
| 347 | } |
| 348 | |
| 349 | /* |
| 350 | * Note simple_write_begin does not read the page from disk on partial writes |
| 351 | * this is ok since vboxsf_write_end only writes the written parts of the |
| 352 | * page and it does not call SetPageUptodate for partial writes. |
| 353 | */ |
| 354 | const struct address_space_operations vboxsf_reg_aops = { |
| 355 | .readpage = vboxsf_readpage, |
| 356 | .writepage = vboxsf_writepage, |
| 357 | .set_page_dirty = __set_page_dirty_nobuffers, |
| 358 | .write_begin = simple_write_begin, |
| 359 | .write_end = vboxsf_write_end, |
| 360 | }; |
| 361 | |
| 362 | static const char *vboxsf_get_link(struct dentry *dentry, struct inode *inode, |
| 363 | struct delayed_call *done) |
| 364 | { |
| 365 | struct vboxsf_sbi *sbi = VBOXSF_SBI(inode->i_sb); |
| 366 | struct shfl_string *path; |
| 367 | char *link; |
| 368 | int err; |
| 369 | |
| 370 | if (!dentry) |
| 371 | return ERR_PTR(-ECHILD); |
| 372 | |
| 373 | path = vboxsf_path_from_dentry(sbi, dentry); |
| 374 | if (IS_ERR(path)) |
| 375 | return ERR_CAST(path); |
| 376 | |
| 377 | link = kzalloc(PATH_MAX, GFP_KERNEL); |
| 378 | if (!link) { |
| 379 | __putname(path); |
| 380 | return ERR_PTR(-ENOMEM); |
| 381 | } |
| 382 | |
| 383 | err = vboxsf_readlink(sbi->root, path, PATH_MAX, link); |
| 384 | __putname(path); |
| 385 | if (err) { |
| 386 | kfree(link); |
| 387 | return ERR_PTR(err); |
| 388 | } |
| 389 | |
| 390 | set_delayed_call(done, kfree_link, link); |
| 391 | return link; |
| 392 | } |
| 393 | |
| 394 | const struct inode_operations vboxsf_lnk_iops = { |
| 395 | .get_link = vboxsf_get_link |
| 396 | }; |