Merge branch 'work.vboxsf' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs

Pull vboxfs from Al Viro:
"This is the VirtualBox guest shared folder support by Hans de Goede,
with fixups for fs_parse folded in to avoid bisection hazards from
those API changes..."

* 'work.vboxsf' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs:
fs: Add VirtualBox guest shared folder (vboxsf) support

+6
MAINTAINERS
··· 17791 17791 F: include/uapi/linux/vbox*.h 17792 17792 F: drivers/virt/vboxguest/ 17793 17793 17794 + VIRTUAL BOX SHARED FOLDER VFS DRIVER: 17795 + M: Hans de Goede <hdegoede@redhat.com> 17796 + L: linux-fsdevel@vger.kernel.org 17797 + S: Maintained 17798 + F: fs/vboxsf/* 17799 + 17794 17800 VIRTUAL SERIO DEVICE DRIVER 17795 17801 M: Stephen Chandler Paul <thatslyude@gmail.com> 17796 17802 S: Maintained
+1
fs/Kconfig
··· 264 264 source "fs/sysv/Kconfig" 265 265 source "fs/ufs/Kconfig" 266 266 source "fs/erofs/Kconfig" 267 + source "fs/vboxsf/Kconfig" 267 268 268 269 endif # MISC_FILESYSTEMS 269 270
+1
fs/Makefile
··· 133 133 obj-$(CONFIG_PSTORE) += pstore/ 134 134 obj-$(CONFIG_EFIVAR_FS) += efivarfs/ 135 135 obj-$(CONFIG_EROFS_FS) += erofs/ 136 + obj-$(CONFIG_VBOXSF_FS) += vboxsf/
+10
fs/vboxsf/Kconfig
··· 1 + config VBOXSF_FS 2 + tristate "VirtualBox guest shared folder (vboxsf) support" 3 + depends on X86 && VBOXGUEST 4 + select NLS 5 + help 6 + VirtualBox hosts can share folders with guests, this driver 7 + implements the Linux-guest side of this allowing folders exported 8 + by the host to be mounted under Linux. 9 + 10 + If you want to use shared folders in VirtualBox guests, answer Y or M.
+5
fs/vboxsf/Makefile
··· 1 + # SPDX-License-Identifier: MIT 2 + 3 + obj-$(CONFIG_VBOXSF_FS) += vboxsf.o 4 + 5 + vboxsf-y := dir.o file.o utils.o vboxsf_wrappers.o super.o
+427
fs/vboxsf/dir.c
··· 1 + // SPDX-License-Identifier: MIT 2 + /* 3 + * VirtualBox Guest Shared Folders support: Directory inode and file operations 4 + * 5 + * Copyright (C) 2006-2018 Oracle Corporation 6 + */ 7 + 8 + #include <linux/namei.h> 9 + #include <linux/vbox_utils.h> 10 + #include "vfsmod.h" 11 + 12 + static int vboxsf_dir_open(struct inode *inode, struct file *file) 13 + { 14 + struct vboxsf_sbi *sbi = VBOXSF_SBI(inode->i_sb); 15 + struct shfl_createparms params = {}; 16 + struct vboxsf_dir_info *sf_d; 17 + int err; 18 + 19 + sf_d = vboxsf_dir_info_alloc(); 20 + if (!sf_d) 21 + return -ENOMEM; 22 + 23 + params.handle = SHFL_HANDLE_NIL; 24 + params.create_flags = SHFL_CF_DIRECTORY | SHFL_CF_ACT_OPEN_IF_EXISTS | 25 + SHFL_CF_ACT_FAIL_IF_NEW | SHFL_CF_ACCESS_READ; 26 + 27 + err = vboxsf_create_at_dentry(file_dentry(file), &params); 28 + if (err) 29 + goto err_free_dir_info; 30 + 31 + if (params.result != SHFL_FILE_EXISTS) { 32 + err = -ENOENT; 33 + goto err_close; 34 + } 35 + 36 + err = vboxsf_dir_read_all(sbi, sf_d, params.handle); 37 + if (err) 38 + goto err_close; 39 + 40 + vboxsf_close(sbi->root, params.handle); 41 + file->private_data = sf_d; 42 + return 0; 43 + 44 + err_close: 45 + vboxsf_close(sbi->root, params.handle); 46 + err_free_dir_info: 47 + vboxsf_dir_info_free(sf_d); 48 + return err; 49 + } 50 + 51 + static int vboxsf_dir_release(struct inode *inode, struct file *file) 52 + { 53 + if (file->private_data) 54 + vboxsf_dir_info_free(file->private_data); 55 + 56 + return 0; 57 + } 58 + 59 + static unsigned int vboxsf_get_d_type(u32 mode) 60 + { 61 + unsigned int d_type; 62 + 63 + switch (mode & SHFL_TYPE_MASK) { 64 + case SHFL_TYPE_FIFO: 65 + d_type = DT_FIFO; 66 + break; 67 + case SHFL_TYPE_DEV_CHAR: 68 + d_type = DT_CHR; 69 + break; 70 + case SHFL_TYPE_DIRECTORY: 71 + d_type = DT_DIR; 72 + break; 73 + case SHFL_TYPE_DEV_BLOCK: 74 + d_type = DT_BLK; 75 + break; 76 + case SHFL_TYPE_FILE: 77 + d_type = DT_REG; 78 + break; 79 + case SHFL_TYPE_SYMLINK: 80 + d_type = DT_LNK; 81 + break; 82 + case SHFL_TYPE_SOCKET: 83 + d_type = DT_SOCK; 84 + break; 85 + case SHFL_TYPE_WHITEOUT: 86 + d_type = DT_WHT; 87 + break; 88 + default: 89 + d_type = DT_UNKNOWN; 90 + break; 91 + } 92 + return d_type; 93 + } 94 + 95 + static bool vboxsf_dir_emit(struct file *dir, struct dir_context *ctx) 96 + { 97 + struct vboxsf_sbi *sbi = VBOXSF_SBI(file_inode(dir)->i_sb); 98 + struct vboxsf_dir_info *sf_d = dir->private_data; 99 + struct shfl_dirinfo *info; 100 + struct vboxsf_dir_buf *b; 101 + unsigned int d_type; 102 + loff_t i, cur = 0; 103 + ino_t fake_ino; 104 + void *end; 105 + int err; 106 + 107 + list_for_each_entry(b, &sf_d->info_list, head) { 108 + try_next_entry: 109 + if (ctx->pos >= cur + b->entries) { 110 + cur += b->entries; 111 + continue; 112 + } 113 + 114 + /* 115 + * Note the vboxsf_dir_info objects we are iterating over here 116 + * are variable sized, so the info pointer may end up being 117 + * unaligned. This is how we get the data from the host. 118 + * Since vboxsf is only supported on x86 machines this is not 119 + * a problem. 120 + */ 121 + for (i = 0, info = b->buf; i < ctx->pos - cur; i++) { 122 + end = &info->name.string.utf8[info->name.size]; 123 + /* Only happens if the host gives us corrupt data */ 124 + if (WARN_ON(end > (b->buf + b->used))) 125 + return false; 126 + info = end; 127 + } 128 + 129 + end = &info->name.string.utf8[info->name.size]; 130 + if (WARN_ON(end > (b->buf + b->used))) 131 + return false; 132 + 133 + /* Info now points to the right entry, emit it. */ 134 + d_type = vboxsf_get_d_type(info->info.attr.mode); 135 + 136 + /* 137 + * On 32 bit systems pos is 64 signed, while ino is 32 bit 138 + * unsigned so fake_ino may overflow, check for this. 139 + */ 140 + if ((ino_t)(ctx->pos + 1) != (u64)(ctx->pos + 1)) { 141 + vbg_err("vboxsf: fake ino overflow, truncating dir\n"); 142 + return false; 143 + } 144 + fake_ino = ctx->pos + 1; 145 + 146 + if (sbi->nls) { 147 + char d_name[NAME_MAX]; 148 + 149 + err = vboxsf_nlscpy(sbi, d_name, NAME_MAX, 150 + info->name.string.utf8, 151 + info->name.length); 152 + if (err) { 153 + /* skip erroneous entry and proceed */ 154 + ctx->pos += 1; 155 + goto try_next_entry; 156 + } 157 + 158 + return dir_emit(ctx, d_name, strlen(d_name), 159 + fake_ino, d_type); 160 + } 161 + 162 + return dir_emit(ctx, info->name.string.utf8, info->name.length, 163 + fake_ino, d_type); 164 + } 165 + 166 + return false; 167 + } 168 + 169 + static int vboxsf_dir_iterate(struct file *dir, struct dir_context *ctx) 170 + { 171 + bool emitted; 172 + 173 + do { 174 + emitted = vboxsf_dir_emit(dir, ctx); 175 + if (emitted) 176 + ctx->pos += 1; 177 + } while (emitted); 178 + 179 + return 0; 180 + } 181 + 182 + const struct file_operations vboxsf_dir_fops = { 183 + .open = vboxsf_dir_open, 184 + .iterate = vboxsf_dir_iterate, 185 + .release = vboxsf_dir_release, 186 + .read = generic_read_dir, 187 + .llseek = generic_file_llseek, 188 + }; 189 + 190 + /* 191 + * This is called during name resolution/lookup to check if the @dentry in 192 + * the cache is still valid. the job is handled by vboxsf_inode_revalidate. 193 + */ 194 + static int vboxsf_dentry_revalidate(struct dentry *dentry, unsigned int flags) 195 + { 196 + if (flags & LOOKUP_RCU) 197 + return -ECHILD; 198 + 199 + if (d_really_is_positive(dentry)) 200 + return vboxsf_inode_revalidate(dentry) == 0; 201 + else 202 + return vboxsf_stat_dentry(dentry, NULL) == -ENOENT; 203 + } 204 + 205 + const struct dentry_operations vboxsf_dentry_ops = { 206 + .d_revalidate = vboxsf_dentry_revalidate 207 + }; 208 + 209 + /* iops */ 210 + 211 + static struct dentry *vboxsf_dir_lookup(struct inode *parent, 212 + struct dentry *dentry, 213 + unsigned int flags) 214 + { 215 + struct vboxsf_sbi *sbi = VBOXSF_SBI(parent->i_sb); 216 + struct shfl_fsobjinfo fsinfo; 217 + struct inode *inode; 218 + int err; 219 + 220 + dentry->d_time = jiffies; 221 + 222 + err = vboxsf_stat_dentry(dentry, &fsinfo); 223 + if (err) { 224 + inode = (err == -ENOENT) ? NULL : ERR_PTR(err); 225 + } else { 226 + inode = vboxsf_new_inode(parent->i_sb); 227 + if (!IS_ERR(inode)) 228 + vboxsf_init_inode(sbi, inode, &fsinfo); 229 + } 230 + 231 + return d_splice_alias(inode, dentry); 232 + } 233 + 234 + static int vboxsf_dir_instantiate(struct inode *parent, struct dentry *dentry, 235 + struct shfl_fsobjinfo *info) 236 + { 237 + struct vboxsf_sbi *sbi = VBOXSF_SBI(parent->i_sb); 238 + struct vboxsf_inode *sf_i; 239 + struct inode *inode; 240 + 241 + inode = vboxsf_new_inode(parent->i_sb); 242 + if (IS_ERR(inode)) 243 + return PTR_ERR(inode); 244 + 245 + sf_i = VBOXSF_I(inode); 246 + /* The host may have given us different attr then requested */ 247 + sf_i->force_restat = 1; 248 + vboxsf_init_inode(sbi, inode, info); 249 + 250 + d_instantiate(dentry, inode); 251 + 252 + return 0; 253 + } 254 + 255 + static int vboxsf_dir_create(struct inode *parent, struct dentry *dentry, 256 + umode_t mode, int is_dir) 257 + { 258 + struct vboxsf_inode *sf_parent_i = VBOXSF_I(parent); 259 + struct vboxsf_sbi *sbi = VBOXSF_SBI(parent->i_sb); 260 + struct shfl_createparms params = {}; 261 + int err; 262 + 263 + params.handle = SHFL_HANDLE_NIL; 264 + params.create_flags = SHFL_CF_ACT_CREATE_IF_NEW | 265 + SHFL_CF_ACT_FAIL_IF_EXISTS | 266 + SHFL_CF_ACCESS_READWRITE | 267 + (is_dir ? SHFL_CF_DIRECTORY : 0); 268 + params.info.attr.mode = (mode & 0777) | 269 + (is_dir ? SHFL_TYPE_DIRECTORY : SHFL_TYPE_FILE); 270 + params.info.attr.additional = SHFLFSOBJATTRADD_NOTHING; 271 + 272 + err = vboxsf_create_at_dentry(dentry, &params); 273 + if (err) 274 + return err; 275 + 276 + if (params.result != SHFL_FILE_CREATED) 277 + return -EPERM; 278 + 279 + vboxsf_close(sbi->root, params.handle); 280 + 281 + err = vboxsf_dir_instantiate(parent, dentry, &params.info); 282 + if (err) 283 + return err; 284 + 285 + /* parent directory access/change time changed */ 286 + sf_parent_i->force_restat = 1; 287 + 288 + return 0; 289 + } 290 + 291 + static int vboxsf_dir_mkfile(struct inode *parent, struct dentry *dentry, 292 + umode_t mode, bool excl) 293 + { 294 + return vboxsf_dir_create(parent, dentry, mode, 0); 295 + } 296 + 297 + static int vboxsf_dir_mkdir(struct inode *parent, struct dentry *dentry, 298 + umode_t mode) 299 + { 300 + return vboxsf_dir_create(parent, dentry, mode, 1); 301 + } 302 + 303 + static int vboxsf_dir_unlink(struct inode *parent, struct dentry *dentry) 304 + { 305 + struct vboxsf_sbi *sbi = VBOXSF_SBI(parent->i_sb); 306 + struct vboxsf_inode *sf_parent_i = VBOXSF_I(parent); 307 + struct inode *inode = d_inode(dentry); 308 + struct shfl_string *path; 309 + u32 flags; 310 + int err; 311 + 312 + if (S_ISDIR(inode->i_mode)) 313 + flags = SHFL_REMOVE_DIR; 314 + else 315 + flags = SHFL_REMOVE_FILE; 316 + 317 + if (S_ISLNK(inode->i_mode)) 318 + flags |= SHFL_REMOVE_SYMLINK; 319 + 320 + path = vboxsf_path_from_dentry(sbi, dentry); 321 + if (IS_ERR(path)) 322 + return PTR_ERR(path); 323 + 324 + err = vboxsf_remove(sbi->root, path, flags); 325 + __putname(path); 326 + if (err) 327 + return err; 328 + 329 + /* parent directory access/change time changed */ 330 + sf_parent_i->force_restat = 1; 331 + 332 + return 0; 333 + } 334 + 335 + static int vboxsf_dir_rename(struct inode *old_parent, 336 + struct dentry *old_dentry, 337 + struct inode *new_parent, 338 + struct dentry *new_dentry, 339 + unsigned int flags) 340 + { 341 + struct vboxsf_sbi *sbi = VBOXSF_SBI(old_parent->i_sb); 342 + struct vboxsf_inode *sf_old_parent_i = VBOXSF_I(old_parent); 343 + struct vboxsf_inode *sf_new_parent_i = VBOXSF_I(new_parent); 344 + u32 shfl_flags = SHFL_RENAME_FILE | SHFL_RENAME_REPLACE_IF_EXISTS; 345 + struct shfl_string *old_path, *new_path; 346 + int err; 347 + 348 + if (flags) 349 + return -EINVAL; 350 + 351 + old_path = vboxsf_path_from_dentry(sbi, old_dentry); 352 + if (IS_ERR(old_path)) 353 + return PTR_ERR(old_path); 354 + 355 + new_path = vboxsf_path_from_dentry(sbi, new_dentry); 356 + if (IS_ERR(new_path)) { 357 + err = PTR_ERR(new_path); 358 + goto err_put_old_path; 359 + } 360 + 361 + if (d_inode(old_dentry)->i_mode & S_IFDIR) 362 + shfl_flags = 0; 363 + 364 + err = vboxsf_rename(sbi->root, old_path, new_path, shfl_flags); 365 + if (err == 0) { 366 + /* parent directories access/change time changed */ 367 + sf_new_parent_i->force_restat = 1; 368 + sf_old_parent_i->force_restat = 1; 369 + } 370 + 371 + __putname(new_path); 372 + err_put_old_path: 373 + __putname(old_path); 374 + return err; 375 + } 376 + 377 + static int vboxsf_dir_symlink(struct inode *parent, struct dentry *dentry, 378 + const char *symname) 379 + { 380 + struct vboxsf_inode *sf_parent_i = VBOXSF_I(parent); 381 + struct vboxsf_sbi *sbi = VBOXSF_SBI(parent->i_sb); 382 + int symname_size = strlen(symname) + 1; 383 + struct shfl_string *path, *ssymname; 384 + struct shfl_fsobjinfo info; 385 + int err; 386 + 387 + path = vboxsf_path_from_dentry(sbi, dentry); 388 + if (IS_ERR(path)) 389 + return PTR_ERR(path); 390 + 391 + ssymname = kmalloc(SHFLSTRING_HEADER_SIZE + symname_size, GFP_KERNEL); 392 + if (!ssymname) { 393 + __putname(path); 394 + return -ENOMEM; 395 + } 396 + ssymname->length = symname_size - 1; 397 + ssymname->size = symname_size; 398 + memcpy(ssymname->string.utf8, symname, symname_size); 399 + 400 + err = vboxsf_symlink(sbi->root, path, ssymname, &info); 401 + kfree(ssymname); 402 + __putname(path); 403 + if (err) { 404 + /* -EROFS means symlinks are note support -> -EPERM */ 405 + return (err == -EROFS) ? -EPERM : err; 406 + } 407 + 408 + err = vboxsf_dir_instantiate(parent, dentry, &info); 409 + if (err) 410 + return err; 411 + 412 + /* parent directory access/change time changed */ 413 + sf_parent_i->force_restat = 1; 414 + return 0; 415 + } 416 + 417 + const struct inode_operations vboxsf_dir_iops = { 418 + .lookup = vboxsf_dir_lookup, 419 + .create = vboxsf_dir_mkfile, 420 + .mkdir = vboxsf_dir_mkdir, 421 + .rmdir = vboxsf_dir_unlink, 422 + .unlink = vboxsf_dir_unlink, 423 + .rename = vboxsf_dir_rename, 424 + .symlink = vboxsf_dir_symlink, 425 + .getattr = vboxsf_getattr, 426 + .setattr = vboxsf_setattr, 427 + };
+379
fs/vboxsf/file.c
··· 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 + 23 + static int vboxsf_file_open(struct inode *inode, struct file *file) 24 + { 25 + struct vboxsf_inode *sf_i = VBOXSF_I(inode); 26 + struct shfl_createparms params = {}; 27 + struct vboxsf_handle *sf_handle; 28 + u32 access_flags = 0; 29 + int err; 30 + 31 + sf_handle = kmalloc(sizeof(*sf_handle), GFP_KERNEL); 32 + if (!sf_handle) 33 + return -ENOMEM; 34 + 35 + /* 36 + * We check the value of params.handle afterwards to find out if 37 + * the call succeeded or failed, as the API does not seem to cleanly 38 + * distinguish error and informational messages. 39 + * 40 + * Furthermore, we must set params.handle to SHFL_HANDLE_NIL to 41 + * make the shared folders host service use our mode parameter. 42 + */ 43 + params.handle = SHFL_HANDLE_NIL; 44 + if (file->f_flags & O_CREAT) { 45 + params.create_flags |= SHFL_CF_ACT_CREATE_IF_NEW; 46 + /* 47 + * We ignore O_EXCL, as the Linux kernel seems to call create 48 + * beforehand itself, so O_EXCL should always fail. 49 + */ 50 + if (file->f_flags & O_TRUNC) 51 + params.create_flags |= SHFL_CF_ACT_OVERWRITE_IF_EXISTS; 52 + else 53 + params.create_flags |= SHFL_CF_ACT_OPEN_IF_EXISTS; 54 + } else { 55 + params.create_flags |= SHFL_CF_ACT_FAIL_IF_NEW; 56 + if (file->f_flags & O_TRUNC) 57 + params.create_flags |= SHFL_CF_ACT_OVERWRITE_IF_EXISTS; 58 + } 59 + 60 + switch (file->f_flags & O_ACCMODE) { 61 + case O_RDONLY: 62 + access_flags |= SHFL_CF_ACCESS_READ; 63 + break; 64 + 65 + case O_WRONLY: 66 + access_flags |= SHFL_CF_ACCESS_WRITE; 67 + break; 68 + 69 + case O_RDWR: 70 + access_flags |= SHFL_CF_ACCESS_READWRITE; 71 + break; 72 + 73 + default: 74 + WARN_ON(1); 75 + } 76 + 77 + if (file->f_flags & O_APPEND) 78 + access_flags |= SHFL_CF_ACCESS_APPEND; 79 + 80 + params.create_flags |= access_flags; 81 + params.info.attr.mode = inode->i_mode; 82 + 83 + err = vboxsf_create_at_dentry(file_dentry(file), &params); 84 + if (err == 0 && params.handle == SHFL_HANDLE_NIL) 85 + err = (params.result == SHFL_FILE_EXISTS) ? -EEXIST : -ENOENT; 86 + if (err) { 87 + kfree(sf_handle); 88 + return err; 89 + } 90 + 91 + /* the host may have given us different attr then requested */ 92 + sf_i->force_restat = 1; 93 + 94 + /* init our handle struct and add it to the inode's handles list */ 95 + sf_handle->handle = params.handle; 96 + sf_handle->root = VBOXSF_SBI(inode->i_sb)->root; 97 + sf_handle->access_flags = access_flags; 98 + kref_init(&sf_handle->refcount); 99 + 100 + mutex_lock(&sf_i->handle_list_mutex); 101 + list_add(&sf_handle->head, &sf_i->handle_list); 102 + mutex_unlock(&sf_i->handle_list_mutex); 103 + 104 + file->private_data = sf_handle; 105 + return 0; 106 + } 107 + 108 + static void vboxsf_handle_release(struct kref *refcount) 109 + { 110 + struct vboxsf_handle *sf_handle = 111 + container_of(refcount, struct vboxsf_handle, refcount); 112 + 113 + vboxsf_close(sf_handle->root, sf_handle->handle); 114 + kfree(sf_handle); 115 + } 116 + 117 + static int vboxsf_file_release(struct inode *inode, struct file *file) 118 + { 119 + struct vboxsf_inode *sf_i = VBOXSF_I(inode); 120 + struct vboxsf_handle *sf_handle = file->private_data; 121 + 122 + /* 123 + * When a file is closed on our (the guest) side, we want any subsequent 124 + * accesses done on the host side to see all changes done from our side. 125 + */ 126 + filemap_write_and_wait(inode->i_mapping); 127 + 128 + mutex_lock(&sf_i->handle_list_mutex); 129 + list_del(&sf_handle->head); 130 + mutex_unlock(&sf_i->handle_list_mutex); 131 + 132 + kref_put(&sf_handle->refcount, vboxsf_handle_release); 133 + return 0; 134 + } 135 + 136 + /* 137 + * Write back dirty pages now, because there may not be any suitable 138 + * open files later 139 + */ 140 + static void vboxsf_vma_close(struct vm_area_struct *vma) 141 + { 142 + filemap_write_and_wait(vma->vm_file->f_mapping); 143 + } 144 + 145 + static const struct vm_operations_struct vboxsf_file_vm_ops = { 146 + .close = vboxsf_vma_close, 147 + .fault = filemap_fault, 148 + .map_pages = filemap_map_pages, 149 + }; 150 + 151 + static int vboxsf_file_mmap(struct file *file, struct vm_area_struct *vma) 152 + { 153 + int err; 154 + 155 + err = generic_file_mmap(file, vma); 156 + if (!err) 157 + vma->vm_ops = &vboxsf_file_vm_ops; 158 + 159 + return err; 160 + } 161 + 162 + /* 163 + * Note that since we are accessing files on the host's filesystem, files 164 + * may always be changed underneath us by the host! 165 + * 166 + * The vboxsf API between the guest and the host does not offer any functions 167 + * to deal with this. There is no inode-generation to check for changes, no 168 + * events / callback on changes and no way to lock files. 169 + * 170 + * To avoid returning stale data when a file gets *opened* on our (the guest) 171 + * side, we do a "stat" on the host side, then compare the mtime with the 172 + * last known mtime and invalidate the page-cache if they differ. 173 + * This is done from vboxsf_inode_revalidate(). 174 + * 175 + * When reads are done through the read_iter fop, it is possible to do 176 + * further cache revalidation then, there are 3 options to deal with this: 177 + * 178 + * 1) Rely solely on the revalidation done at open time 179 + * 2) Do another "stat" and compare mtime again. Unfortunately the vboxsf 180 + * host API does not allow stat on handles, so we would need to use 181 + * file->f_path.dentry and the stat will then fail if the file was unlinked 182 + * or renamed (and there is no thing like NFS' silly-rename). So we get: 183 + * 2a) "stat" and compare mtime, on stat failure invalidate the cache 184 + * 2b) "stat" and compare mtime, on stat failure do nothing 185 + * 3) Simply always call invalidate_inode_pages2_range on the range of the read 186 + * 187 + * Currently we are keeping things KISS and using option 1. this allows 188 + * directly using generic_file_read_iter without wrapping it. 189 + * 190 + * This means that only data written on the host side before open() on 191 + * the guest side is guaranteed to be seen by the guest. If necessary 192 + * we may provide other read-cache strategies in the future and make this 193 + * configurable through a mount option. 194 + */ 195 + const struct file_operations vboxsf_reg_fops = { 196 + .llseek = generic_file_llseek, 197 + .read_iter = generic_file_read_iter, 198 + .write_iter = generic_file_write_iter, 199 + .mmap = vboxsf_file_mmap, 200 + .open = vboxsf_file_open, 201 + .release = vboxsf_file_release, 202 + .fsync = noop_fsync, 203 + .splice_read = generic_file_splice_read, 204 + }; 205 + 206 + const struct inode_operations vboxsf_reg_iops = { 207 + .getattr = vboxsf_getattr, 208 + .setattr = vboxsf_setattr 209 + }; 210 + 211 + static int vboxsf_readpage(struct file *file, struct page *page) 212 + { 213 + struct vboxsf_handle *sf_handle = file->private_data; 214 + loff_t off = page_offset(page); 215 + u32 nread = PAGE_SIZE; 216 + u8 *buf; 217 + int err; 218 + 219 + buf = kmap(page); 220 + 221 + err = vboxsf_read(sf_handle->root, sf_handle->handle, off, &nread, buf); 222 + if (err == 0) { 223 + memset(&buf[nread], 0, PAGE_SIZE - nread); 224 + flush_dcache_page(page); 225 + SetPageUptodate(page); 226 + } else { 227 + SetPageError(page); 228 + } 229 + 230 + kunmap(page); 231 + unlock_page(page); 232 + return err; 233 + } 234 + 235 + static struct vboxsf_handle *vboxsf_get_write_handle(struct vboxsf_inode *sf_i) 236 + { 237 + struct vboxsf_handle *h, *sf_handle = NULL; 238 + 239 + mutex_lock(&sf_i->handle_list_mutex); 240 + list_for_each_entry(h, &sf_i->handle_list, head) { 241 + if (h->access_flags == SHFL_CF_ACCESS_WRITE || 242 + h->access_flags == SHFL_CF_ACCESS_READWRITE) { 243 + kref_get(&h->refcount); 244 + sf_handle = h; 245 + break; 246 + } 247 + } 248 + mutex_unlock(&sf_i->handle_list_mutex); 249 + 250 + return sf_handle; 251 + } 252 + 253 + static int vboxsf_writepage(struct page *page, struct writeback_control *wbc) 254 + { 255 + struct inode *inode = page->mapping->host; 256 + struct vboxsf_inode *sf_i = VBOXSF_I(inode); 257 + struct vboxsf_handle *sf_handle; 258 + loff_t off = page_offset(page); 259 + loff_t size = i_size_read(inode); 260 + u32 nwrite = PAGE_SIZE; 261 + u8 *buf; 262 + int err; 263 + 264 + if (off + PAGE_SIZE > size) 265 + nwrite = size & ~PAGE_MASK; 266 + 267 + sf_handle = vboxsf_get_write_handle(sf_i); 268 + if (!sf_handle) 269 + return -EBADF; 270 + 271 + buf = kmap(page); 272 + err = vboxsf_write(sf_handle->root, sf_handle->handle, 273 + off, &nwrite, buf); 274 + kunmap(page); 275 + 276 + kref_put(&sf_handle->refcount, vboxsf_handle_release); 277 + 278 + if (err == 0) { 279 + ClearPageError(page); 280 + /* mtime changed */ 281 + sf_i->force_restat = 1; 282 + } else { 283 + ClearPageUptodate(page); 284 + } 285 + 286 + unlock_page(page); 287 + return err; 288 + } 289 + 290 + static int vboxsf_write_end(struct file *file, struct address_space *mapping, 291 + loff_t pos, unsigned int len, unsigned int copied, 292 + struct page *page, void *fsdata) 293 + { 294 + struct inode *inode = mapping->host; 295 + struct vboxsf_handle *sf_handle = file->private_data; 296 + unsigned int from = pos & ~PAGE_MASK; 297 + u32 nwritten = len; 298 + u8 *buf; 299 + int err; 300 + 301 + /* zero the stale part of the page if we did a short copy */ 302 + if (!PageUptodate(page) && copied < len) 303 + zero_user(page, from + copied, len - copied); 304 + 305 + buf = kmap(page); 306 + err = vboxsf_write(sf_handle->root, sf_handle->handle, 307 + pos, &nwritten, buf + from); 308 + kunmap(page); 309 + 310 + if (err) { 311 + nwritten = 0; 312 + goto out; 313 + } 314 + 315 + /* mtime changed */ 316 + VBOXSF_I(inode)->force_restat = 1; 317 + 318 + if (!PageUptodate(page) && nwritten == PAGE_SIZE) 319 + SetPageUptodate(page); 320 + 321 + pos += nwritten; 322 + if (pos > inode->i_size) 323 + i_size_write(inode, pos); 324 + 325 + out: 326 + unlock_page(page); 327 + put_page(page); 328 + 329 + return nwritten; 330 + } 331 + 332 + /* 333 + * Note simple_write_begin does not read the page from disk on partial writes 334 + * this is ok since vboxsf_write_end only writes the written parts of the 335 + * page and it does not call SetPageUptodate for partial writes. 336 + */ 337 + const struct address_space_operations vboxsf_reg_aops = { 338 + .readpage = vboxsf_readpage, 339 + .writepage = vboxsf_writepage, 340 + .set_page_dirty = __set_page_dirty_nobuffers, 341 + .write_begin = simple_write_begin, 342 + .write_end = vboxsf_write_end, 343 + }; 344 + 345 + static const char *vboxsf_get_link(struct dentry *dentry, struct inode *inode, 346 + struct delayed_call *done) 347 + { 348 + struct vboxsf_sbi *sbi = VBOXSF_SBI(inode->i_sb); 349 + struct shfl_string *path; 350 + char *link; 351 + int err; 352 + 353 + if (!dentry) 354 + return ERR_PTR(-ECHILD); 355 + 356 + path = vboxsf_path_from_dentry(sbi, dentry); 357 + if (IS_ERR(path)) 358 + return ERR_CAST(path); 359 + 360 + link = kzalloc(PATH_MAX, GFP_KERNEL); 361 + if (!link) { 362 + __putname(path); 363 + return ERR_PTR(-ENOMEM); 364 + } 365 + 366 + err = vboxsf_readlink(sbi->root, path, PATH_MAX, link); 367 + __putname(path); 368 + if (err) { 369 + kfree(link); 370 + return ERR_PTR(err); 371 + } 372 + 373 + set_delayed_call(done, kfree_link, link); 374 + return link; 375 + } 376 + 377 + const struct inode_operations vboxsf_lnk_iops = { 378 + .get_link = vboxsf_get_link 379 + };
+901
fs/vboxsf/shfl_hostintf.h
··· 1 + /* SPDX-License-Identifier: MIT */ 2 + /* 3 + * VirtualBox Shared Folders: host interface definition. 4 + * 5 + * Copyright (C) 2006-2018 Oracle Corporation 6 + */ 7 + 8 + #ifndef SHFL_HOSTINTF_H 9 + #define SHFL_HOSTINTF_H 10 + 11 + #include <linux/vbox_vmmdev_types.h> 12 + 13 + /* The max in/out buffer size for a FN_READ or FN_WRITE call */ 14 + #define SHFL_MAX_RW_COUNT (16 * SZ_1M) 15 + 16 + /* 17 + * Structures shared between guest and the service 18 + * can be relocated and use offsets to point to variable 19 + * length parts. 20 + * 21 + * Shared folders protocol works with handles. 22 + * Before doing any action on a file system object, 23 + * one have to obtain the object handle via a SHFL_FN_CREATE 24 + * request. A handle must be closed with SHFL_FN_CLOSE. 25 + */ 26 + 27 + enum { 28 + SHFL_FN_QUERY_MAPPINGS = 1, /* Query mappings changes. */ 29 + SHFL_FN_QUERY_MAP_NAME = 2, /* Query map name. */ 30 + SHFL_FN_CREATE = 3, /* Open/create object. */ 31 + SHFL_FN_CLOSE = 4, /* Close object handle. */ 32 + SHFL_FN_READ = 5, /* Read object content. */ 33 + SHFL_FN_WRITE = 6, /* Write new object content. */ 34 + SHFL_FN_LOCK = 7, /* Lock/unlock a range in the object. */ 35 + SHFL_FN_LIST = 8, /* List object content. */ 36 + SHFL_FN_INFORMATION = 9, /* Query/set object information. */ 37 + /* Note function number 10 is not used! */ 38 + SHFL_FN_REMOVE = 11, /* Remove object */ 39 + SHFL_FN_MAP_FOLDER_OLD = 12, /* Map folder (legacy) */ 40 + SHFL_FN_UNMAP_FOLDER = 13, /* Unmap folder */ 41 + SHFL_FN_RENAME = 14, /* Rename object */ 42 + SHFL_FN_FLUSH = 15, /* Flush file */ 43 + SHFL_FN_SET_UTF8 = 16, /* Select UTF8 filename encoding */ 44 + SHFL_FN_MAP_FOLDER = 17, /* Map folder */ 45 + SHFL_FN_READLINK = 18, /* Read symlink dest (as of VBox 4.0) */ 46 + SHFL_FN_SYMLINK = 19, /* Create symlink (as of VBox 4.0) */ 47 + SHFL_FN_SET_SYMLINKS = 20, /* Ask host to show symlinks (4.0+) */ 48 + }; 49 + 50 + /* Root handles for a mapping are of type u32, Root handles are unique. */ 51 + #define SHFL_ROOT_NIL UINT_MAX 52 + 53 + /* Shared folders handle for an opened object are of type u64. */ 54 + #define SHFL_HANDLE_NIL ULLONG_MAX 55 + 56 + /* Hardcoded maximum length (in chars) of a shared folder name. */ 57 + #define SHFL_MAX_LEN (256) 58 + /* Hardcoded maximum number of shared folder mapping available to the guest. */ 59 + #define SHFL_MAX_MAPPINGS (64) 60 + 61 + /** Shared folder string buffer structure. */ 62 + struct shfl_string { 63 + /** Allocated size of the string member in bytes. */ 64 + u16 size; 65 + 66 + /** Length of string without trailing nul in bytes. */ 67 + u16 length; 68 + 69 + /** UTF-8 or UTF-16 string. Nul terminated. */ 70 + union { 71 + u8 utf8[2]; 72 + u16 utf16[1]; 73 + u16 ucs2[1]; /* misnomer, use utf16. */ 74 + } string; 75 + }; 76 + VMMDEV_ASSERT_SIZE(shfl_string, 6); 77 + 78 + /* The size of shfl_string w/o the string part. */ 79 + #define SHFLSTRING_HEADER_SIZE 4 80 + 81 + /* Calculate size of the string. */ 82 + static inline u32 shfl_string_buf_size(const struct shfl_string *string) 83 + { 84 + return string ? SHFLSTRING_HEADER_SIZE + string->size : 0; 85 + } 86 + 87 + /* Set user id on execution (S_ISUID). */ 88 + #define SHFL_UNIX_ISUID 0004000U 89 + /* Set group id on execution (S_ISGID). */ 90 + #define SHFL_UNIX_ISGID 0002000U 91 + /* Sticky bit (S_ISVTX / S_ISTXT). */ 92 + #define SHFL_UNIX_ISTXT 0001000U 93 + 94 + /* Owner readable (S_IRUSR). */ 95 + #define SHFL_UNIX_IRUSR 0000400U 96 + /* Owner writable (S_IWUSR). */ 97 + #define SHFL_UNIX_IWUSR 0000200U 98 + /* Owner executable (S_IXUSR). */ 99 + #define SHFL_UNIX_IXUSR 0000100U 100 + 101 + /* Group readable (S_IRGRP). */ 102 + #define SHFL_UNIX_IRGRP 0000040U 103 + /* Group writable (S_IWGRP). */ 104 + #define SHFL_UNIX_IWGRP 0000020U 105 + /* Group executable (S_IXGRP). */ 106 + #define SHFL_UNIX_IXGRP 0000010U 107 + 108 + /* Other readable (S_IROTH). */ 109 + #define SHFL_UNIX_IROTH 0000004U 110 + /* Other writable (S_IWOTH). */ 111 + #define SHFL_UNIX_IWOTH 0000002U 112 + /* Other executable (S_IXOTH). */ 113 + #define SHFL_UNIX_IXOTH 0000001U 114 + 115 + /* Named pipe (fifo) (S_IFIFO). */ 116 + #define SHFL_TYPE_FIFO 0010000U 117 + /* Character device (S_IFCHR). */ 118 + #define SHFL_TYPE_DEV_CHAR 0020000U 119 + /* Directory (S_IFDIR). */ 120 + #define SHFL_TYPE_DIRECTORY 0040000U 121 + /* Block device (S_IFBLK). */ 122 + #define SHFL_TYPE_DEV_BLOCK 0060000U 123 + /* Regular file (S_IFREG). */ 124 + #define SHFL_TYPE_FILE 0100000U 125 + /* Symbolic link (S_IFLNK). */ 126 + #define SHFL_TYPE_SYMLINK 0120000U 127 + /* Socket (S_IFSOCK). */ 128 + #define SHFL_TYPE_SOCKET 0140000U 129 + /* Whiteout (S_IFWHT). */ 130 + #define SHFL_TYPE_WHITEOUT 0160000U 131 + /* Type mask (S_IFMT). */ 132 + #define SHFL_TYPE_MASK 0170000U 133 + 134 + /* Checks the mode flags indicate a directory (S_ISDIR). */ 135 + #define SHFL_IS_DIRECTORY(m) (((m) & SHFL_TYPE_MASK) == SHFL_TYPE_DIRECTORY) 136 + /* Checks the mode flags indicate a symbolic link (S_ISLNK). */ 137 + #define SHFL_IS_SYMLINK(m) (((m) & SHFL_TYPE_MASK) == SHFL_TYPE_SYMLINK) 138 + 139 + /** The available additional information in a shfl_fsobjattr object. */ 140 + enum shfl_fsobjattr_add { 141 + /** No additional information is available / requested. */ 142 + SHFLFSOBJATTRADD_NOTHING = 1, 143 + /** 144 + * The additional unix attributes (shfl_fsobjattr::u::unix_attr) are 145 + * available / requested. 146 + */ 147 + SHFLFSOBJATTRADD_UNIX, 148 + /** 149 + * The additional extended attribute size (shfl_fsobjattr::u::size) is 150 + * available / requested. 151 + */ 152 + SHFLFSOBJATTRADD_EASIZE, 153 + /** 154 + * The last valid item (inclusive). 155 + * The valid range is SHFLFSOBJATTRADD_NOTHING thru 156 + * SHFLFSOBJATTRADD_LAST. 157 + */ 158 + SHFLFSOBJATTRADD_LAST = SHFLFSOBJATTRADD_EASIZE, 159 + 160 + /** The usual 32-bit hack. */ 161 + SHFLFSOBJATTRADD_32BIT_SIZE_HACK = 0x7fffffff 162 + }; 163 + 164 + /** 165 + * Additional unix Attributes, these are available when 166 + * shfl_fsobjattr.additional == SHFLFSOBJATTRADD_UNIX. 167 + */ 168 + struct shfl_fsobjattr_unix { 169 + /** 170 + * The user owning the filesystem object (st_uid). 171 + * This field is ~0U if not supported. 172 + */ 173 + u32 uid; 174 + 175 + /** 176 + * The group the filesystem object is assigned (st_gid). 177 + * This field is ~0U if not supported. 178 + */ 179 + u32 gid; 180 + 181 + /** 182 + * Number of hard links to this filesystem object (st_nlink). 183 + * This field is 1 if the filesystem doesn't support hardlinking or 184 + * the information isn't available. 185 + */ 186 + u32 hardlinks; 187 + 188 + /** 189 + * The device number of the device which this filesystem object resides 190 + * on (st_dev). This field is 0 if this information is not available. 191 + */ 192 + u32 inode_id_device; 193 + 194 + /** 195 + * The unique identifier (within the filesystem) of this filesystem 196 + * object (st_ino). Together with inode_id_device, this field can be 197 + * used as a OS wide unique id, when both their values are not 0. 198 + * This field is 0 if the information is not available. 199 + */ 200 + u64 inode_id; 201 + 202 + /** 203 + * User flags (st_flags). 204 + * This field is 0 if this information is not available. 205 + */ 206 + u32 flags; 207 + 208 + /** 209 + * The current generation number (st_gen). 210 + * This field is 0 if this information is not available. 211 + */ 212 + u32 generation_id; 213 + 214 + /** 215 + * The device number of a char. or block device type object (st_rdev). 216 + * This field is 0 if the file isn't a char. or block device or when 217 + * the OS doesn't use the major+minor device idenfication scheme. 218 + */ 219 + u32 device; 220 + } __packed; 221 + 222 + /** Extended attribute size. */ 223 + struct shfl_fsobjattr_easize { 224 + /** Size of EAs. */ 225 + s64 cb; 226 + } __packed; 227 + 228 + /** Shared folder filesystem object attributes. */ 229 + struct shfl_fsobjattr { 230 + /** Mode flags (st_mode). SHFL_UNIX_*, SHFL_TYPE_*, and SHFL_DOS_*. */ 231 + u32 mode; 232 + 233 + /** The additional attributes available. */ 234 + enum shfl_fsobjattr_add additional; 235 + 236 + /** 237 + * Additional attributes. 238 + * 239 + * Unless explicitly specified to an API, the API can provide additional 240 + * data as it is provided by the underlying OS. 241 + */ 242 + union { 243 + struct shfl_fsobjattr_unix unix_attr; 244 + struct shfl_fsobjattr_easize size; 245 + } __packed u; 246 + } __packed; 247 + VMMDEV_ASSERT_SIZE(shfl_fsobjattr, 44); 248 + 249 + struct shfl_timespec { 250 + s64 ns_relative_to_unix_epoch; 251 + }; 252 + 253 + /** Filesystem object information structure. */ 254 + struct shfl_fsobjinfo { 255 + /** 256 + * Logical size (st_size). 257 + * For normal files this is the size of the file. 258 + * For symbolic links, this is the length of the path name contained 259 + * in the symbolic link. 260 + * For other objects this fields needs to be specified. 261 + */ 262 + s64 size; 263 + 264 + /** Disk allocation size (st_blocks * DEV_BSIZE). */ 265 + s64 allocated; 266 + 267 + /** Time of last access (st_atime). */ 268 + struct shfl_timespec access_time; 269 + 270 + /** Time of last data modification (st_mtime). */ 271 + struct shfl_timespec modification_time; 272 + 273 + /** 274 + * Time of last status change (st_ctime). 275 + * If not available this is set to modification_time. 276 + */ 277 + struct shfl_timespec change_time; 278 + 279 + /** 280 + * Time of file birth (st_birthtime). 281 + * If not available this is set to change_time. 282 + */ 283 + struct shfl_timespec birth_time; 284 + 285 + /** Attributes. */ 286 + struct shfl_fsobjattr attr; 287 + 288 + } __packed; 289 + VMMDEV_ASSERT_SIZE(shfl_fsobjinfo, 92); 290 + 291 + /** 292 + * result of an open/create request. 293 + * Along with handle value the result code 294 + * identifies what has happened while 295 + * trying to open the object. 296 + */ 297 + enum shfl_create_result { 298 + SHFL_NO_RESULT, 299 + /** Specified path does not exist. */ 300 + SHFL_PATH_NOT_FOUND, 301 + /** Path to file exists, but the last component does not. */ 302 + SHFL_FILE_NOT_FOUND, 303 + /** File already exists and either has been opened or not. */ 304 + SHFL_FILE_EXISTS, 305 + /** New file was created. */ 306 + SHFL_FILE_CREATED, 307 + /** Existing file was replaced or overwritten. */ 308 + SHFL_FILE_REPLACED 309 + }; 310 + 311 + /* No flags. Initialization value. */ 312 + #define SHFL_CF_NONE (0x00000000) 313 + 314 + /* 315 + * Only lookup the object, do not return a handle. When this is set all other 316 + * flags are ignored. 317 + */ 318 + #define SHFL_CF_LOOKUP (0x00000001) 319 + 320 + /* 321 + * Open parent directory of specified object. 322 + * Useful for the corresponding Windows FSD flag 323 + * and for opening paths like \\dir\\*.* to search the 'dir'. 324 + */ 325 + #define SHFL_CF_OPEN_TARGET_DIRECTORY (0x00000002) 326 + 327 + /* Create/open a directory. */ 328 + #define SHFL_CF_DIRECTORY (0x00000004) 329 + 330 + /* 331 + * Open/create action to do if object exists 332 + * and if the object does not exists. 333 + * REPLACE file means atomically DELETE and CREATE. 334 + * OVERWRITE file means truncating the file to 0 and 335 + * setting new size. 336 + * When opening an existing directory REPLACE and OVERWRITE 337 + * actions are considered invalid, and cause returning 338 + * FILE_EXISTS with NIL handle. 339 + */ 340 + #define SHFL_CF_ACT_MASK_IF_EXISTS (0x000000f0) 341 + #define SHFL_CF_ACT_MASK_IF_NEW (0x00000f00) 342 + 343 + /* What to do if object exists. */ 344 + #define SHFL_CF_ACT_OPEN_IF_EXISTS (0x00000000) 345 + #define SHFL_CF_ACT_FAIL_IF_EXISTS (0x00000010) 346 + #define SHFL_CF_ACT_REPLACE_IF_EXISTS (0x00000020) 347 + #define SHFL_CF_ACT_OVERWRITE_IF_EXISTS (0x00000030) 348 + 349 + /* What to do if object does not exist. */ 350 + #define SHFL_CF_ACT_CREATE_IF_NEW (0x00000000) 351 + #define SHFL_CF_ACT_FAIL_IF_NEW (0x00000100) 352 + 353 + /* Read/write requested access for the object. */ 354 + #define SHFL_CF_ACCESS_MASK_RW (0x00003000) 355 + 356 + /* No access requested. */ 357 + #define SHFL_CF_ACCESS_NONE (0x00000000) 358 + /* Read access requested. */ 359 + #define SHFL_CF_ACCESS_READ (0x00001000) 360 + /* Write access requested. */ 361 + #define SHFL_CF_ACCESS_WRITE (0x00002000) 362 + /* Read/Write access requested. */ 363 + #define SHFL_CF_ACCESS_READWRITE (0x00003000) 364 + 365 + /* Requested share access for the object. */ 366 + #define SHFL_CF_ACCESS_MASK_DENY (0x0000c000) 367 + 368 + /* Allow any access. */ 369 + #define SHFL_CF_ACCESS_DENYNONE (0x00000000) 370 + /* Do not allow read. */ 371 + #define SHFL_CF_ACCESS_DENYREAD (0x00004000) 372 + /* Do not allow write. */ 373 + #define SHFL_CF_ACCESS_DENYWRITE (0x00008000) 374 + /* Do not allow access. */ 375 + #define SHFL_CF_ACCESS_DENYALL (0x0000c000) 376 + 377 + /* Requested access to attributes of the object. */ 378 + #define SHFL_CF_ACCESS_MASK_ATTR (0x00030000) 379 + 380 + /* No access requested. */ 381 + #define SHFL_CF_ACCESS_ATTR_NONE (0x00000000) 382 + /* Read access requested. */ 383 + #define SHFL_CF_ACCESS_ATTR_READ (0x00010000) 384 + /* Write access requested. */ 385 + #define SHFL_CF_ACCESS_ATTR_WRITE (0x00020000) 386 + /* Read/Write access requested. */ 387 + #define SHFL_CF_ACCESS_ATTR_READWRITE (0x00030000) 388 + 389 + /* 390 + * The file is opened in append mode. 391 + * Ignored if SHFL_CF_ACCESS_WRITE is not set. 392 + */ 393 + #define SHFL_CF_ACCESS_APPEND (0x00040000) 394 + 395 + /** Create parameters buffer struct for SHFL_FN_CREATE call */ 396 + struct shfl_createparms { 397 + /** Returned handle of opened object. */ 398 + u64 handle; 399 + 400 + /** Returned result of the operation */ 401 + enum shfl_create_result result; 402 + 403 + /** SHFL_CF_* */ 404 + u32 create_flags; 405 + 406 + /** 407 + * Attributes of object to create and 408 + * returned actual attributes of opened/created object. 409 + */ 410 + struct shfl_fsobjinfo info; 411 + } __packed; 412 + 413 + /** Shared Folder directory information */ 414 + struct shfl_dirinfo { 415 + /** Full information about the object. */ 416 + struct shfl_fsobjinfo info; 417 + /** 418 + * The length of the short field (number of UTF16 chars). 419 + * It is 16-bit for reasons of alignment. 420 + */ 421 + u16 short_name_len; 422 + /** 423 + * The short name for 8.3 compatibility. 424 + * Empty string if not available. 425 + */ 426 + u16 short_name[14]; 427 + struct shfl_string name; 428 + }; 429 + 430 + /** Shared folder filesystem properties. */ 431 + struct shfl_fsproperties { 432 + /** 433 + * The maximum size of a filesystem object name. 434 + * This does not include the '\\0'. 435 + */ 436 + u32 max_component_len; 437 + 438 + /** 439 + * True if the filesystem is remote. 440 + * False if the filesystem is local. 441 + */ 442 + bool remote; 443 + 444 + /** 445 + * True if the filesystem is case sensitive. 446 + * False if the filesystem is case insensitive. 447 + */ 448 + bool case_sensitive; 449 + 450 + /** 451 + * True if the filesystem is mounted read only. 452 + * False if the filesystem is mounted read write. 453 + */ 454 + bool read_only; 455 + 456 + /** 457 + * True if the filesystem can encode unicode object names. 458 + * False if it can't. 459 + */ 460 + bool supports_unicode; 461 + 462 + /** 463 + * True if the filesystem is compresses. 464 + * False if it isn't or we don't know. 465 + */ 466 + bool compressed; 467 + 468 + /** 469 + * True if the filesystem compresses of individual files. 470 + * False if it doesn't or we don't know. 471 + */ 472 + bool file_compression; 473 + }; 474 + VMMDEV_ASSERT_SIZE(shfl_fsproperties, 12); 475 + 476 + struct shfl_volinfo { 477 + s64 total_allocation_bytes; 478 + s64 available_allocation_bytes; 479 + u32 bytes_per_allocation_unit; 480 + u32 bytes_per_sector; 481 + u32 serial; 482 + struct shfl_fsproperties properties; 483 + }; 484 + 485 + 486 + /** SHFL_FN_MAP_FOLDER Parameters structure. */ 487 + struct shfl_map_folder { 488 + /** 489 + * pointer, in: 490 + * Points to struct shfl_string buffer. 491 + */ 492 + struct vmmdev_hgcm_function_parameter path; 493 + 494 + /** 495 + * pointer, out: SHFLROOT (u32) 496 + * Root handle of the mapping which name is queried. 497 + */ 498 + struct vmmdev_hgcm_function_parameter root; 499 + 500 + /** 501 + * pointer, in: UTF16 502 + * Path delimiter 503 + */ 504 + struct vmmdev_hgcm_function_parameter delimiter; 505 + 506 + /** 507 + * pointer, in: SHFLROOT (u32) 508 + * Case senstive flag 509 + */ 510 + struct vmmdev_hgcm_function_parameter case_sensitive; 511 + 512 + }; 513 + 514 + /* Number of parameters */ 515 + #define SHFL_CPARMS_MAP_FOLDER (4) 516 + 517 + 518 + /** SHFL_FN_UNMAP_FOLDER Parameters structure. */ 519 + struct shfl_unmap_folder { 520 + /** 521 + * pointer, in: SHFLROOT (u32) 522 + * Root handle of the mapping which name is queried. 523 + */ 524 + struct vmmdev_hgcm_function_parameter root; 525 + 526 + }; 527 + 528 + /* Number of parameters */ 529 + #define SHFL_CPARMS_UNMAP_FOLDER (1) 530 + 531 + 532 + /** SHFL_FN_CREATE Parameters structure. */ 533 + struct shfl_create { 534 + /** 535 + * pointer, in: SHFLROOT (u32) 536 + * Root handle of the mapping which name is queried. 537 + */ 538 + struct vmmdev_hgcm_function_parameter root; 539 + 540 + /** 541 + * pointer, in: 542 + * Points to struct shfl_string buffer. 543 + */ 544 + struct vmmdev_hgcm_function_parameter path; 545 + 546 + /** 547 + * pointer, in/out: 548 + * Points to struct shfl_createparms buffer. 549 + */ 550 + struct vmmdev_hgcm_function_parameter parms; 551 + 552 + }; 553 + 554 + /* Number of parameters */ 555 + #define SHFL_CPARMS_CREATE (3) 556 + 557 + 558 + /** SHFL_FN_CLOSE Parameters structure. */ 559 + struct shfl_close { 560 + /** 561 + * pointer, in: SHFLROOT (u32) 562 + * Root handle of the mapping which name is queried. 563 + */ 564 + struct vmmdev_hgcm_function_parameter root; 565 + 566 + /** 567 + * value64, in: 568 + * SHFLHANDLE (u64) of object to close. 569 + */ 570 + struct vmmdev_hgcm_function_parameter handle; 571 + 572 + }; 573 + 574 + /* Number of parameters */ 575 + #define SHFL_CPARMS_CLOSE (2) 576 + 577 + 578 + /** SHFL_FN_READ Parameters structure. */ 579 + struct shfl_read { 580 + /** 581 + * pointer, in: SHFLROOT (u32) 582 + * Root handle of the mapping which name is queried. 583 + */ 584 + struct vmmdev_hgcm_function_parameter root; 585 + 586 + /** 587 + * value64, in: 588 + * SHFLHANDLE (u64) of object to read from. 589 + */ 590 + struct vmmdev_hgcm_function_parameter handle; 591 + 592 + /** 593 + * value64, in: 594 + * Offset to read from. 595 + */ 596 + struct vmmdev_hgcm_function_parameter offset; 597 + 598 + /** 599 + * value64, in/out: 600 + * Bytes to read/How many were read. 601 + */ 602 + struct vmmdev_hgcm_function_parameter cb; 603 + 604 + /** 605 + * pointer, out: 606 + * Buffer to place data to. 607 + */ 608 + struct vmmdev_hgcm_function_parameter buffer; 609 + 610 + }; 611 + 612 + /* Number of parameters */ 613 + #define SHFL_CPARMS_READ (5) 614 + 615 + 616 + /** SHFL_FN_WRITE Parameters structure. */ 617 + struct shfl_write { 618 + /** 619 + * pointer, in: SHFLROOT (u32) 620 + * Root handle of the mapping which name is queried. 621 + */ 622 + struct vmmdev_hgcm_function_parameter root; 623 + 624 + /** 625 + * value64, in: 626 + * SHFLHANDLE (u64) of object to write to. 627 + */ 628 + struct vmmdev_hgcm_function_parameter handle; 629 + 630 + /** 631 + * value64, in: 632 + * Offset to write to. 633 + */ 634 + struct vmmdev_hgcm_function_parameter offset; 635 + 636 + /** 637 + * value64, in/out: 638 + * Bytes to write/How many were written. 639 + */ 640 + struct vmmdev_hgcm_function_parameter cb; 641 + 642 + /** 643 + * pointer, in: 644 + * Data to write. 645 + */ 646 + struct vmmdev_hgcm_function_parameter buffer; 647 + 648 + }; 649 + 650 + /* Number of parameters */ 651 + #define SHFL_CPARMS_WRITE (5) 652 + 653 + 654 + /* 655 + * SHFL_FN_LIST 656 + * Listing information includes variable length RTDIRENTRY[EX] structures. 657 + */ 658 + 659 + #define SHFL_LIST_NONE 0 660 + #define SHFL_LIST_RETURN_ONE 1 661 + 662 + /** SHFL_FN_LIST Parameters structure. */ 663 + struct shfl_list { 664 + /** 665 + * pointer, in: SHFLROOT (u32) 666 + * Root handle of the mapping which name is queried. 667 + */ 668 + struct vmmdev_hgcm_function_parameter root; 669 + 670 + /** 671 + * value64, in: 672 + * SHFLHANDLE (u64) of object to be listed. 673 + */ 674 + struct vmmdev_hgcm_function_parameter handle; 675 + 676 + /** 677 + * value32, in: 678 + * List flags SHFL_LIST_*. 679 + */ 680 + struct vmmdev_hgcm_function_parameter flags; 681 + 682 + /** 683 + * value32, in/out: 684 + * Bytes to be used for listing information/How many bytes were used. 685 + */ 686 + struct vmmdev_hgcm_function_parameter cb; 687 + 688 + /** 689 + * pointer, in/optional 690 + * Points to struct shfl_string buffer that specifies a search path. 691 + */ 692 + struct vmmdev_hgcm_function_parameter path; 693 + 694 + /** 695 + * pointer, out: 696 + * Buffer to place listing information to. (struct shfl_dirinfo) 697 + */ 698 + struct vmmdev_hgcm_function_parameter buffer; 699 + 700 + /** 701 + * value32, in/out: 702 + * Indicates a key where the listing must be resumed. 703 + * in: 0 means start from begin of object. 704 + * out: 0 means listing completed. 705 + */ 706 + struct vmmdev_hgcm_function_parameter resume_point; 707 + 708 + /** 709 + * pointer, out: 710 + * Number of files returned 711 + */ 712 + struct vmmdev_hgcm_function_parameter file_count; 713 + }; 714 + 715 + /* Number of parameters */ 716 + #define SHFL_CPARMS_LIST (8) 717 + 718 + 719 + /** SHFL_FN_READLINK Parameters structure. */ 720 + struct shfl_readLink { 721 + /** 722 + * pointer, in: SHFLROOT (u32) 723 + * Root handle of the mapping which name is queried. 724 + */ 725 + struct vmmdev_hgcm_function_parameter root; 726 + 727 + /** 728 + * pointer, in: 729 + * Points to struct shfl_string buffer. 730 + */ 731 + struct vmmdev_hgcm_function_parameter path; 732 + 733 + /** 734 + * pointer, out: 735 + * Buffer to place data to. 736 + */ 737 + struct vmmdev_hgcm_function_parameter buffer; 738 + 739 + }; 740 + 741 + /* Number of parameters */ 742 + #define SHFL_CPARMS_READLINK (3) 743 + 744 + 745 + /* SHFL_FN_INFORMATION */ 746 + 747 + /* Mask of Set/Get bit. */ 748 + #define SHFL_INFO_MODE_MASK (0x1) 749 + /* Get information */ 750 + #define SHFL_INFO_GET (0x0) 751 + /* Set information */ 752 + #define SHFL_INFO_SET (0x1) 753 + 754 + /* Get name of the object. */ 755 + #define SHFL_INFO_NAME (0x2) 756 + /* Set size of object (extend/trucate); only applies to file objects */ 757 + #define SHFL_INFO_SIZE (0x4) 758 + /* Get/Set file object info. */ 759 + #define SHFL_INFO_FILE (0x8) 760 + /* Get volume information. */ 761 + #define SHFL_INFO_VOLUME (0x10) 762 + 763 + /** SHFL_FN_INFORMATION Parameters structure. */ 764 + struct shfl_information { 765 + /** 766 + * pointer, in: SHFLROOT (u32) 767 + * Root handle of the mapping which name is queried. 768 + */ 769 + struct vmmdev_hgcm_function_parameter root; 770 + 771 + /** 772 + * value64, in: 773 + * SHFLHANDLE (u64) of object to be listed. 774 + */ 775 + struct vmmdev_hgcm_function_parameter handle; 776 + 777 + /** 778 + * value32, in: 779 + * SHFL_INFO_* 780 + */ 781 + struct vmmdev_hgcm_function_parameter flags; 782 + 783 + /** 784 + * value32, in/out: 785 + * Bytes to be used for information/How many bytes were used. 786 + */ 787 + struct vmmdev_hgcm_function_parameter cb; 788 + 789 + /** 790 + * pointer, in/out: 791 + * Information to be set/get (shfl_fsobjinfo or shfl_string). Do not 792 + * forget to set the shfl_fsobjinfo::attr::additional for a get 793 + * operation as well. 794 + */ 795 + struct vmmdev_hgcm_function_parameter info; 796 + 797 + }; 798 + 799 + /* Number of parameters */ 800 + #define SHFL_CPARMS_INFORMATION (5) 801 + 802 + 803 + /* SHFL_FN_REMOVE */ 804 + 805 + #define SHFL_REMOVE_FILE (0x1) 806 + #define SHFL_REMOVE_DIR (0x2) 807 + #define SHFL_REMOVE_SYMLINK (0x4) 808 + 809 + /** SHFL_FN_REMOVE Parameters structure. */ 810 + struct shfl_remove { 811 + /** 812 + * pointer, in: SHFLROOT (u32) 813 + * Root handle of the mapping which name is queried. 814 + */ 815 + struct vmmdev_hgcm_function_parameter root; 816 + 817 + /** 818 + * pointer, in: 819 + * Points to struct shfl_string buffer. 820 + */ 821 + struct vmmdev_hgcm_function_parameter path; 822 + 823 + /** 824 + * value32, in: 825 + * remove flags (file/directory) 826 + */ 827 + struct vmmdev_hgcm_function_parameter flags; 828 + 829 + }; 830 + 831 + #define SHFL_CPARMS_REMOVE (3) 832 + 833 + 834 + /* SHFL_FN_RENAME */ 835 + 836 + #define SHFL_RENAME_FILE (0x1) 837 + #define SHFL_RENAME_DIR (0x2) 838 + #define SHFL_RENAME_REPLACE_IF_EXISTS (0x4) 839 + 840 + /** SHFL_FN_RENAME Parameters structure. */ 841 + struct shfl_rename { 842 + /** 843 + * pointer, in: SHFLROOT (u32) 844 + * Root handle of the mapping which name is queried. 845 + */ 846 + struct vmmdev_hgcm_function_parameter root; 847 + 848 + /** 849 + * pointer, in: 850 + * Points to struct shfl_string src. 851 + */ 852 + struct vmmdev_hgcm_function_parameter src; 853 + 854 + /** 855 + * pointer, in: 856 + * Points to struct shfl_string dest. 857 + */ 858 + struct vmmdev_hgcm_function_parameter dest; 859 + 860 + /** 861 + * value32, in: 862 + * rename flags (file/directory) 863 + */ 864 + struct vmmdev_hgcm_function_parameter flags; 865 + 866 + }; 867 + 868 + #define SHFL_CPARMS_RENAME (4) 869 + 870 + 871 + /** SHFL_FN_SYMLINK Parameters structure. */ 872 + struct shfl_symlink { 873 + /** 874 + * pointer, in: SHFLROOT (u32) 875 + * Root handle of the mapping which name is queried. 876 + */ 877 + struct vmmdev_hgcm_function_parameter root; 878 + 879 + /** 880 + * pointer, in: 881 + * Points to struct shfl_string of path for the new symlink. 882 + */ 883 + struct vmmdev_hgcm_function_parameter new_path; 884 + 885 + /** 886 + * pointer, in: 887 + * Points to struct shfl_string of destination for symlink. 888 + */ 889 + struct vmmdev_hgcm_function_parameter old_path; 890 + 891 + /** 892 + * pointer, out: 893 + * Information about created symlink. 894 + */ 895 + struct vmmdev_hgcm_function_parameter info; 896 + 897 + }; 898 + 899 + #define SHFL_CPARMS_SYMLINK (4) 900 + 901 + #endif
+491
fs/vboxsf/super.c
··· 1 + // SPDX-License-Identifier: MIT 2 + /* 3 + * VirtualBox Guest Shared Folders support: Virtual File System. 4 + * 5 + * Module initialization/finalization 6 + * File system registration/deregistration 7 + * Superblock reading 8 + * Few utility functions 9 + * 10 + * Copyright (C) 2006-2018 Oracle Corporation 11 + */ 12 + 13 + #include <linux/idr.h> 14 + #include <linux/fs_parser.h> 15 + #include <linux/magic.h> 16 + #include <linux/module.h> 17 + #include <linux/nls.h> 18 + #include <linux/statfs.h> 19 + #include <linux/vbox_utils.h> 20 + #include "vfsmod.h" 21 + 22 + #define VBOXSF_SUPER_MAGIC 0x786f4256 /* 'VBox' little endian */ 23 + 24 + #define VBSF_MOUNT_SIGNATURE_BYTE_0 ('\000') 25 + #define VBSF_MOUNT_SIGNATURE_BYTE_1 ('\377') 26 + #define VBSF_MOUNT_SIGNATURE_BYTE_2 ('\376') 27 + #define VBSF_MOUNT_SIGNATURE_BYTE_3 ('\375') 28 + 29 + static int follow_symlinks; 30 + module_param(follow_symlinks, int, 0444); 31 + MODULE_PARM_DESC(follow_symlinks, 32 + "Let host resolve symlinks rather than showing them"); 33 + 34 + static DEFINE_IDA(vboxsf_bdi_ida); 35 + static DEFINE_MUTEX(vboxsf_setup_mutex); 36 + static bool vboxsf_setup_done; 37 + static struct super_operations vboxsf_super_ops; /* forward declaration */ 38 + static struct kmem_cache *vboxsf_inode_cachep; 39 + 40 + static char * const vboxsf_default_nls = CONFIG_NLS_DEFAULT; 41 + 42 + enum { opt_nls, opt_uid, opt_gid, opt_ttl, opt_dmode, opt_fmode, 43 + opt_dmask, opt_fmask }; 44 + 45 + static const struct fs_parameter_spec vboxsf_fs_parameters[] = { 46 + fsparam_string ("nls", opt_nls), 47 + fsparam_u32 ("uid", opt_uid), 48 + fsparam_u32 ("gid", opt_gid), 49 + fsparam_u32 ("ttl", opt_ttl), 50 + fsparam_u32oct ("dmode", opt_dmode), 51 + fsparam_u32oct ("fmode", opt_fmode), 52 + fsparam_u32oct ("dmask", opt_dmask), 53 + fsparam_u32oct ("fmask", opt_fmask), 54 + {} 55 + }; 56 + 57 + static int vboxsf_parse_param(struct fs_context *fc, struct fs_parameter *param) 58 + { 59 + struct vboxsf_fs_context *ctx = fc->fs_private; 60 + struct fs_parse_result result; 61 + kuid_t uid; 62 + kgid_t gid; 63 + int opt; 64 + 65 + opt = fs_parse(fc, vboxsf_fs_parameters, param, &result); 66 + if (opt < 0) 67 + return opt; 68 + 69 + switch (opt) { 70 + case opt_nls: 71 + if (ctx->nls_name || fc->purpose != FS_CONTEXT_FOR_MOUNT) { 72 + vbg_err("vboxsf: Cannot reconfigure nls option\n"); 73 + return -EINVAL; 74 + } 75 + ctx->nls_name = param->string; 76 + param->string = NULL; 77 + break; 78 + case opt_uid: 79 + uid = make_kuid(current_user_ns(), result.uint_32); 80 + if (!uid_valid(uid)) 81 + return -EINVAL; 82 + ctx->o.uid = uid; 83 + break; 84 + case opt_gid: 85 + gid = make_kgid(current_user_ns(), result.uint_32); 86 + if (!gid_valid(gid)) 87 + return -EINVAL; 88 + ctx->o.gid = gid; 89 + break; 90 + case opt_ttl: 91 + ctx->o.ttl = msecs_to_jiffies(result.uint_32); 92 + break; 93 + case opt_dmode: 94 + if (result.uint_32 & ~0777) 95 + return -EINVAL; 96 + ctx->o.dmode = result.uint_32; 97 + ctx->o.dmode_set = true; 98 + break; 99 + case opt_fmode: 100 + if (result.uint_32 & ~0777) 101 + return -EINVAL; 102 + ctx->o.fmode = result.uint_32; 103 + ctx->o.fmode_set = true; 104 + break; 105 + case opt_dmask: 106 + if (result.uint_32 & ~07777) 107 + return -EINVAL; 108 + ctx->o.dmask = result.uint_32; 109 + break; 110 + case opt_fmask: 111 + if (result.uint_32 & ~07777) 112 + return -EINVAL; 113 + ctx->o.fmask = result.uint_32; 114 + break; 115 + default: 116 + return -EINVAL; 117 + } 118 + 119 + return 0; 120 + } 121 + 122 + static int vboxsf_fill_super(struct super_block *sb, struct fs_context *fc) 123 + { 124 + struct vboxsf_fs_context *ctx = fc->fs_private; 125 + struct shfl_string *folder_name, root_path; 126 + struct vboxsf_sbi *sbi; 127 + struct dentry *droot; 128 + struct inode *iroot; 129 + char *nls_name; 130 + size_t size; 131 + int err; 132 + 133 + if (!fc->source) 134 + return -EINVAL; 135 + 136 + sbi = kzalloc(sizeof(*sbi), GFP_KERNEL); 137 + if (!sbi) 138 + return -ENOMEM; 139 + 140 + sbi->o = ctx->o; 141 + idr_init(&sbi->ino_idr); 142 + spin_lock_init(&sbi->ino_idr_lock); 143 + sbi->next_generation = 1; 144 + sbi->bdi_id = -1; 145 + 146 + /* Load nls if not utf8 */ 147 + nls_name = ctx->nls_name ? ctx->nls_name : vboxsf_default_nls; 148 + if (strcmp(nls_name, "utf8") != 0) { 149 + if (nls_name == vboxsf_default_nls) 150 + sbi->nls = load_nls_default(); 151 + else 152 + sbi->nls = load_nls(nls_name); 153 + 154 + if (!sbi->nls) { 155 + vbg_err("vboxsf: Count not load '%s' nls\n", nls_name); 156 + err = -EINVAL; 157 + goto fail_free; 158 + } 159 + } 160 + 161 + sbi->bdi_id = ida_simple_get(&vboxsf_bdi_ida, 0, 0, GFP_KERNEL); 162 + if (sbi->bdi_id < 0) { 163 + err = sbi->bdi_id; 164 + goto fail_free; 165 + } 166 + 167 + err = super_setup_bdi_name(sb, "vboxsf-%s.%d", fc->source, sbi->bdi_id); 168 + if (err) 169 + goto fail_free; 170 + 171 + /* Turn source into a shfl_string and map the folder */ 172 + size = strlen(fc->source) + 1; 173 + folder_name = kmalloc(SHFLSTRING_HEADER_SIZE + size, GFP_KERNEL); 174 + if (!folder_name) { 175 + err = -ENOMEM; 176 + goto fail_free; 177 + } 178 + folder_name->size = size; 179 + folder_name->length = size - 1; 180 + strlcpy(folder_name->string.utf8, fc->source, size); 181 + err = vboxsf_map_folder(folder_name, &sbi->root); 182 + kfree(folder_name); 183 + if (err) { 184 + vbg_err("vboxsf: Host rejected mount of '%s' with error %d\n", 185 + fc->source, err); 186 + goto fail_free; 187 + } 188 + 189 + root_path.length = 1; 190 + root_path.size = 2; 191 + root_path.string.utf8[0] = '/'; 192 + root_path.string.utf8[1] = 0; 193 + err = vboxsf_stat(sbi, &root_path, &sbi->root_info); 194 + if (err) 195 + goto fail_unmap; 196 + 197 + sb->s_magic = VBOXSF_SUPER_MAGIC; 198 + sb->s_blocksize = 1024; 199 + sb->s_maxbytes = MAX_LFS_FILESIZE; 200 + sb->s_op = &vboxsf_super_ops; 201 + sb->s_d_op = &vboxsf_dentry_ops; 202 + 203 + iroot = iget_locked(sb, 0); 204 + if (!iroot) { 205 + err = -ENOMEM; 206 + goto fail_unmap; 207 + } 208 + vboxsf_init_inode(sbi, iroot, &sbi->root_info); 209 + unlock_new_inode(iroot); 210 + 211 + droot = d_make_root(iroot); 212 + if (!droot) { 213 + err = -ENOMEM; 214 + goto fail_unmap; 215 + } 216 + 217 + sb->s_root = droot; 218 + sb->s_fs_info = sbi; 219 + return 0; 220 + 221 + fail_unmap: 222 + vboxsf_unmap_folder(sbi->root); 223 + fail_free: 224 + if (sbi->bdi_id >= 0) 225 + ida_simple_remove(&vboxsf_bdi_ida, sbi->bdi_id); 226 + if (sbi->nls) 227 + unload_nls(sbi->nls); 228 + idr_destroy(&sbi->ino_idr); 229 + kfree(sbi); 230 + return err; 231 + } 232 + 233 + static void vboxsf_inode_init_once(void *data) 234 + { 235 + struct vboxsf_inode *sf_i = data; 236 + 237 + mutex_init(&sf_i->handle_list_mutex); 238 + inode_init_once(&sf_i->vfs_inode); 239 + } 240 + 241 + static struct inode *vboxsf_alloc_inode(struct super_block *sb) 242 + { 243 + struct vboxsf_inode *sf_i; 244 + 245 + sf_i = kmem_cache_alloc(vboxsf_inode_cachep, GFP_NOFS); 246 + if (!sf_i) 247 + return NULL; 248 + 249 + sf_i->force_restat = 0; 250 + INIT_LIST_HEAD(&sf_i->handle_list); 251 + 252 + return &sf_i->vfs_inode; 253 + } 254 + 255 + static void vboxsf_free_inode(struct inode *inode) 256 + { 257 + struct vboxsf_sbi *sbi = VBOXSF_SBI(inode->i_sb); 258 + unsigned long flags; 259 + 260 + spin_lock_irqsave(&sbi->ino_idr_lock, flags); 261 + idr_remove(&sbi->ino_idr, inode->i_ino); 262 + spin_unlock_irqrestore(&sbi->ino_idr_lock, flags); 263 + kmem_cache_free(vboxsf_inode_cachep, VBOXSF_I(inode)); 264 + } 265 + 266 + static void vboxsf_put_super(struct super_block *sb) 267 + { 268 + struct vboxsf_sbi *sbi = VBOXSF_SBI(sb); 269 + 270 + vboxsf_unmap_folder(sbi->root); 271 + if (sbi->bdi_id >= 0) 272 + ida_simple_remove(&vboxsf_bdi_ida, sbi->bdi_id); 273 + if (sbi->nls) 274 + unload_nls(sbi->nls); 275 + 276 + /* 277 + * vboxsf_free_inode uses the idr, make sure all delayed rcu free 278 + * inodes are flushed. 279 + */ 280 + rcu_barrier(); 281 + idr_destroy(&sbi->ino_idr); 282 + kfree(sbi); 283 + } 284 + 285 + static int vboxsf_statfs(struct dentry *dentry, struct kstatfs *stat) 286 + { 287 + struct super_block *sb = dentry->d_sb; 288 + struct shfl_volinfo shfl_volinfo; 289 + struct vboxsf_sbi *sbi; 290 + u32 buf_len; 291 + int err; 292 + 293 + sbi = VBOXSF_SBI(sb); 294 + buf_len = sizeof(shfl_volinfo); 295 + err = vboxsf_fsinfo(sbi->root, 0, SHFL_INFO_GET | SHFL_INFO_VOLUME, 296 + &buf_len, &shfl_volinfo); 297 + if (err) 298 + return err; 299 + 300 + stat->f_type = VBOXSF_SUPER_MAGIC; 301 + stat->f_bsize = shfl_volinfo.bytes_per_allocation_unit; 302 + 303 + do_div(shfl_volinfo.total_allocation_bytes, 304 + shfl_volinfo.bytes_per_allocation_unit); 305 + stat->f_blocks = shfl_volinfo.total_allocation_bytes; 306 + 307 + do_div(shfl_volinfo.available_allocation_bytes, 308 + shfl_volinfo.bytes_per_allocation_unit); 309 + stat->f_bfree = shfl_volinfo.available_allocation_bytes; 310 + stat->f_bavail = shfl_volinfo.available_allocation_bytes; 311 + 312 + stat->f_files = 1000; 313 + /* 314 + * Don't return 0 here since the guest may then think that it is not 315 + * possible to create any more files. 316 + */ 317 + stat->f_ffree = 1000000; 318 + stat->f_fsid.val[0] = 0; 319 + stat->f_fsid.val[1] = 0; 320 + stat->f_namelen = 255; 321 + return 0; 322 + } 323 + 324 + static struct super_operations vboxsf_super_ops = { 325 + .alloc_inode = vboxsf_alloc_inode, 326 + .free_inode = vboxsf_free_inode, 327 + .put_super = vboxsf_put_super, 328 + .statfs = vboxsf_statfs, 329 + }; 330 + 331 + static int vboxsf_setup(void) 332 + { 333 + int err; 334 + 335 + mutex_lock(&vboxsf_setup_mutex); 336 + 337 + if (vboxsf_setup_done) 338 + goto success; 339 + 340 + vboxsf_inode_cachep = 341 + kmem_cache_create("vboxsf_inode_cache", 342 + sizeof(struct vboxsf_inode), 0, 343 + (SLAB_RECLAIM_ACCOUNT | SLAB_MEM_SPREAD | 344 + SLAB_ACCOUNT), 345 + vboxsf_inode_init_once); 346 + if (!vboxsf_inode_cachep) { 347 + err = -ENOMEM; 348 + goto fail_nomem; 349 + } 350 + 351 + err = vboxsf_connect(); 352 + if (err) { 353 + vbg_err("vboxsf: err %d connecting to guest PCI-device\n", err); 354 + vbg_err("vboxsf: make sure you are inside a VirtualBox VM\n"); 355 + vbg_err("vboxsf: and check dmesg for vboxguest errors\n"); 356 + goto fail_free_cache; 357 + } 358 + 359 + err = vboxsf_set_utf8(); 360 + if (err) { 361 + vbg_err("vboxsf_setutf8 error %d\n", err); 362 + goto fail_disconnect; 363 + } 364 + 365 + if (!follow_symlinks) { 366 + err = vboxsf_set_symlinks(); 367 + if (err) 368 + vbg_warn("vboxsf: Unable to show symlinks: %d\n", err); 369 + } 370 + 371 + vboxsf_setup_done = true; 372 + success: 373 + mutex_unlock(&vboxsf_setup_mutex); 374 + return 0; 375 + 376 + fail_disconnect: 377 + vboxsf_disconnect(); 378 + fail_free_cache: 379 + kmem_cache_destroy(vboxsf_inode_cachep); 380 + fail_nomem: 381 + mutex_unlock(&vboxsf_setup_mutex); 382 + return err; 383 + } 384 + 385 + static int vboxsf_parse_monolithic(struct fs_context *fc, void *data) 386 + { 387 + char *options = data; 388 + 389 + if (options && options[0] == VBSF_MOUNT_SIGNATURE_BYTE_0 && 390 + options[1] == VBSF_MOUNT_SIGNATURE_BYTE_1 && 391 + options[2] == VBSF_MOUNT_SIGNATURE_BYTE_2 && 392 + options[3] == VBSF_MOUNT_SIGNATURE_BYTE_3) { 393 + vbg_err("vboxsf: Old binary mount data not supported, remove obsolete mount.vboxsf and/or update your VBoxService.\n"); 394 + return -EINVAL; 395 + } 396 + 397 + return generic_parse_monolithic(fc, data); 398 + } 399 + 400 + static int vboxsf_get_tree(struct fs_context *fc) 401 + { 402 + int err; 403 + 404 + err = vboxsf_setup(); 405 + if (err) 406 + return err; 407 + 408 + return get_tree_nodev(fc, vboxsf_fill_super); 409 + } 410 + 411 + static int vboxsf_reconfigure(struct fs_context *fc) 412 + { 413 + struct vboxsf_sbi *sbi = VBOXSF_SBI(fc->root->d_sb); 414 + struct vboxsf_fs_context *ctx = fc->fs_private; 415 + struct inode *iroot = fc->root->d_sb->s_root->d_inode; 416 + 417 + /* Apply changed options to the root inode */ 418 + sbi->o = ctx->o; 419 + vboxsf_init_inode(sbi, iroot, &sbi->root_info); 420 + 421 + return 0; 422 + } 423 + 424 + static void vboxsf_free_fc(struct fs_context *fc) 425 + { 426 + struct vboxsf_fs_context *ctx = fc->fs_private; 427 + 428 + kfree(ctx->nls_name); 429 + kfree(ctx); 430 + } 431 + 432 + static const struct fs_context_operations vboxsf_context_ops = { 433 + .free = vboxsf_free_fc, 434 + .parse_param = vboxsf_parse_param, 435 + .parse_monolithic = vboxsf_parse_monolithic, 436 + .get_tree = vboxsf_get_tree, 437 + .reconfigure = vboxsf_reconfigure, 438 + }; 439 + 440 + static int vboxsf_init_fs_context(struct fs_context *fc) 441 + { 442 + struct vboxsf_fs_context *ctx; 443 + 444 + ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); 445 + if (!ctx) 446 + return -ENOMEM; 447 + 448 + current_uid_gid(&ctx->o.uid, &ctx->o.gid); 449 + 450 + fc->fs_private = ctx; 451 + fc->ops = &vboxsf_context_ops; 452 + return 0; 453 + } 454 + 455 + static struct file_system_type vboxsf_fs_type = { 456 + .owner = THIS_MODULE, 457 + .name = "vboxsf", 458 + .init_fs_context = vboxsf_init_fs_context, 459 + .kill_sb = kill_anon_super 460 + }; 461 + 462 + /* Module initialization/finalization handlers */ 463 + static int __init vboxsf_init(void) 464 + { 465 + return register_filesystem(&vboxsf_fs_type); 466 + } 467 + 468 + static void __exit vboxsf_fini(void) 469 + { 470 + unregister_filesystem(&vboxsf_fs_type); 471 + 472 + mutex_lock(&vboxsf_setup_mutex); 473 + if (vboxsf_setup_done) { 474 + vboxsf_disconnect(); 475 + /* 476 + * Make sure all delayed rcu free inodes are flushed 477 + * before we destroy the cache. 478 + */ 479 + rcu_barrier(); 480 + kmem_cache_destroy(vboxsf_inode_cachep); 481 + } 482 + mutex_unlock(&vboxsf_setup_mutex); 483 + } 484 + 485 + module_init(vboxsf_init); 486 + module_exit(vboxsf_fini); 487 + 488 + MODULE_DESCRIPTION("Oracle VM VirtualBox Module for Host File System Access"); 489 + MODULE_AUTHOR("Oracle Corporation"); 490 + MODULE_LICENSE("GPL v2"); 491 + MODULE_ALIAS_FS("vboxsf");
+551
fs/vboxsf/utils.c
··· 1 + // SPDX-License-Identifier: MIT 2 + /* 3 + * VirtualBox Guest Shared Folders support: Utility functions. 4 + * Mainly conversion from/to VirtualBox/Linux data structures. 5 + * 6 + * Copyright (C) 2006-2018 Oracle Corporation 7 + */ 8 + 9 + #include <linux/namei.h> 10 + #include <linux/nls.h> 11 + #include <linux/sizes.h> 12 + #include <linux/vfs.h> 13 + #include "vfsmod.h" 14 + 15 + struct inode *vboxsf_new_inode(struct super_block *sb) 16 + { 17 + struct vboxsf_sbi *sbi = VBOXSF_SBI(sb); 18 + struct inode *inode; 19 + unsigned long flags; 20 + int cursor, ret; 21 + u32 gen; 22 + 23 + inode = new_inode(sb); 24 + if (!inode) 25 + return ERR_PTR(-ENOMEM); 26 + 27 + idr_preload(GFP_KERNEL); 28 + spin_lock_irqsave(&sbi->ino_idr_lock, flags); 29 + cursor = idr_get_cursor(&sbi->ino_idr); 30 + ret = idr_alloc_cyclic(&sbi->ino_idr, inode, 1, 0, GFP_ATOMIC); 31 + if (ret >= 0 && ret < cursor) 32 + sbi->next_generation++; 33 + gen = sbi->next_generation; 34 + spin_unlock_irqrestore(&sbi->ino_idr_lock, flags); 35 + idr_preload_end(); 36 + 37 + if (ret < 0) { 38 + iput(inode); 39 + return ERR_PTR(ret); 40 + } 41 + 42 + inode->i_ino = ret; 43 + inode->i_generation = gen; 44 + return inode; 45 + } 46 + 47 + /* set [inode] attributes based on [info], uid/gid based on [sbi] */ 48 + void vboxsf_init_inode(struct vboxsf_sbi *sbi, struct inode *inode, 49 + const struct shfl_fsobjinfo *info) 50 + { 51 + const struct shfl_fsobjattr *attr; 52 + s64 allocated; 53 + int mode; 54 + 55 + attr = &info->attr; 56 + 57 + #define mode_set(r) ((attr->mode & (SHFL_UNIX_##r)) ? (S_##r) : 0) 58 + 59 + mode = mode_set(IRUSR); 60 + mode |= mode_set(IWUSR); 61 + mode |= mode_set(IXUSR); 62 + 63 + mode |= mode_set(IRGRP); 64 + mode |= mode_set(IWGRP); 65 + mode |= mode_set(IXGRP); 66 + 67 + mode |= mode_set(IROTH); 68 + mode |= mode_set(IWOTH); 69 + mode |= mode_set(IXOTH); 70 + 71 + #undef mode_set 72 + 73 + /* We use the host-side values for these */ 74 + inode->i_flags |= S_NOATIME | S_NOCMTIME; 75 + inode->i_mapping->a_ops = &vboxsf_reg_aops; 76 + 77 + if (SHFL_IS_DIRECTORY(attr->mode)) { 78 + inode->i_mode = sbi->o.dmode_set ? sbi->o.dmode : mode; 79 + inode->i_mode &= ~sbi->o.dmask; 80 + inode->i_mode |= S_IFDIR; 81 + inode->i_op = &vboxsf_dir_iops; 82 + inode->i_fop = &vboxsf_dir_fops; 83 + /* 84 + * XXX: this probably should be set to the number of entries 85 + * in the directory plus two (. ..) 86 + */ 87 + set_nlink(inode, 1); 88 + } else if (SHFL_IS_SYMLINK(attr->mode)) { 89 + inode->i_mode = sbi->o.fmode_set ? sbi->o.fmode : mode; 90 + inode->i_mode &= ~sbi->o.fmask; 91 + inode->i_mode |= S_IFLNK; 92 + inode->i_op = &vboxsf_lnk_iops; 93 + set_nlink(inode, 1); 94 + } else { 95 + inode->i_mode = sbi->o.fmode_set ? sbi->o.fmode : mode; 96 + inode->i_mode &= ~sbi->o.fmask; 97 + inode->i_mode |= S_IFREG; 98 + inode->i_op = &vboxsf_reg_iops; 99 + inode->i_fop = &vboxsf_reg_fops; 100 + set_nlink(inode, 1); 101 + } 102 + 103 + inode->i_uid = sbi->o.uid; 104 + inode->i_gid = sbi->o.gid; 105 + 106 + inode->i_size = info->size; 107 + inode->i_blkbits = 12; 108 + /* i_blocks always in units of 512 bytes! */ 109 + allocated = info->allocated + 511; 110 + do_div(allocated, 512); 111 + inode->i_blocks = allocated; 112 + 113 + inode->i_atime = ns_to_timespec64( 114 + info->access_time.ns_relative_to_unix_epoch); 115 + inode->i_ctime = ns_to_timespec64( 116 + info->change_time.ns_relative_to_unix_epoch); 117 + inode->i_mtime = ns_to_timespec64( 118 + info->modification_time.ns_relative_to_unix_epoch); 119 + } 120 + 121 + int vboxsf_create_at_dentry(struct dentry *dentry, 122 + struct shfl_createparms *params) 123 + { 124 + struct vboxsf_sbi *sbi = VBOXSF_SBI(dentry->d_sb); 125 + struct shfl_string *path; 126 + int err; 127 + 128 + path = vboxsf_path_from_dentry(sbi, dentry); 129 + if (IS_ERR(path)) 130 + return PTR_ERR(path); 131 + 132 + err = vboxsf_create(sbi->root, path, params); 133 + __putname(path); 134 + 135 + return err; 136 + } 137 + 138 + int vboxsf_stat(struct vboxsf_sbi *sbi, struct shfl_string *path, 139 + struct shfl_fsobjinfo *info) 140 + { 141 + struct shfl_createparms params = {}; 142 + int err; 143 + 144 + params.handle = SHFL_HANDLE_NIL; 145 + params.create_flags = SHFL_CF_LOOKUP | SHFL_CF_ACT_FAIL_IF_NEW; 146 + 147 + err = vboxsf_create(sbi->root, path, &params); 148 + if (err) 149 + return err; 150 + 151 + if (params.result != SHFL_FILE_EXISTS) 152 + return -ENOENT; 153 + 154 + if (info) 155 + *info = params.info; 156 + 157 + return 0; 158 + } 159 + 160 + int vboxsf_stat_dentry(struct dentry *dentry, struct shfl_fsobjinfo *info) 161 + { 162 + struct vboxsf_sbi *sbi = VBOXSF_SBI(dentry->d_sb); 163 + struct shfl_string *path; 164 + int err; 165 + 166 + path = vboxsf_path_from_dentry(sbi, dentry); 167 + if (IS_ERR(path)) 168 + return PTR_ERR(path); 169 + 170 + err = vboxsf_stat(sbi, path, info); 171 + __putname(path); 172 + return err; 173 + } 174 + 175 + int vboxsf_inode_revalidate(struct dentry *dentry) 176 + { 177 + struct vboxsf_sbi *sbi; 178 + struct vboxsf_inode *sf_i; 179 + struct shfl_fsobjinfo info; 180 + struct timespec64 prev_mtime; 181 + struct inode *inode; 182 + int err; 183 + 184 + if (!dentry || !d_really_is_positive(dentry)) 185 + return -EINVAL; 186 + 187 + inode = d_inode(dentry); 188 + prev_mtime = inode->i_mtime; 189 + sf_i = VBOXSF_I(inode); 190 + sbi = VBOXSF_SBI(dentry->d_sb); 191 + if (!sf_i->force_restat) { 192 + if (time_before(jiffies, dentry->d_time + sbi->o.ttl)) 193 + return 0; 194 + } 195 + 196 + err = vboxsf_stat_dentry(dentry, &info); 197 + if (err) 198 + return err; 199 + 200 + dentry->d_time = jiffies; 201 + sf_i->force_restat = 0; 202 + vboxsf_init_inode(sbi, inode, &info); 203 + 204 + /* 205 + * If the file was changed on the host side we need to invalidate the 206 + * page-cache for it. Note this also gets triggered by our own writes, 207 + * this is unavoidable. 208 + */ 209 + if (timespec64_compare(&inode->i_mtime, &prev_mtime) > 0) 210 + invalidate_inode_pages2(inode->i_mapping); 211 + 212 + return 0; 213 + } 214 + 215 + int vboxsf_getattr(const struct path *path, struct kstat *kstat, 216 + u32 request_mask, unsigned int flags) 217 + { 218 + int err; 219 + struct dentry *dentry = path->dentry; 220 + struct inode *inode = d_inode(dentry); 221 + struct vboxsf_inode *sf_i = VBOXSF_I(inode); 222 + 223 + switch (flags & AT_STATX_SYNC_TYPE) { 224 + case AT_STATX_DONT_SYNC: 225 + err = 0; 226 + break; 227 + case AT_STATX_FORCE_SYNC: 228 + sf_i->force_restat = 1; 229 + /* fall-through */ 230 + default: 231 + err = vboxsf_inode_revalidate(dentry); 232 + } 233 + if (err) 234 + return err; 235 + 236 + generic_fillattr(d_inode(dentry), kstat); 237 + return 0; 238 + } 239 + 240 + int vboxsf_setattr(struct dentry *dentry, struct iattr *iattr) 241 + { 242 + struct vboxsf_inode *sf_i = VBOXSF_I(d_inode(dentry)); 243 + struct vboxsf_sbi *sbi = VBOXSF_SBI(dentry->d_sb); 244 + struct shfl_createparms params = {}; 245 + struct shfl_fsobjinfo info = {}; 246 + u32 buf_len; 247 + int err; 248 + 249 + params.handle = SHFL_HANDLE_NIL; 250 + params.create_flags = SHFL_CF_ACT_OPEN_IF_EXISTS | 251 + SHFL_CF_ACT_FAIL_IF_NEW | 252 + SHFL_CF_ACCESS_ATTR_WRITE; 253 + 254 + /* this is at least required for Posix hosts */ 255 + if (iattr->ia_valid & ATTR_SIZE) 256 + params.create_flags |= SHFL_CF_ACCESS_WRITE; 257 + 258 + err = vboxsf_create_at_dentry(dentry, &params); 259 + if (err || params.result != SHFL_FILE_EXISTS) 260 + return err ? err : -ENOENT; 261 + 262 + #define mode_set(r) ((iattr->ia_mode & (S_##r)) ? SHFL_UNIX_##r : 0) 263 + 264 + /* 265 + * Setting the file size and setting the other attributes has to 266 + * be handled separately. 267 + */ 268 + if (iattr->ia_valid & (ATTR_MODE | ATTR_ATIME | ATTR_MTIME)) { 269 + if (iattr->ia_valid & ATTR_MODE) { 270 + info.attr.mode = mode_set(IRUSR); 271 + info.attr.mode |= mode_set(IWUSR); 272 + info.attr.mode |= mode_set(IXUSR); 273 + info.attr.mode |= mode_set(IRGRP); 274 + info.attr.mode |= mode_set(IWGRP); 275 + info.attr.mode |= mode_set(IXGRP); 276 + info.attr.mode |= mode_set(IROTH); 277 + info.attr.mode |= mode_set(IWOTH); 278 + info.attr.mode |= mode_set(IXOTH); 279 + 280 + if (iattr->ia_mode & S_IFDIR) 281 + info.attr.mode |= SHFL_TYPE_DIRECTORY; 282 + else 283 + info.attr.mode |= SHFL_TYPE_FILE; 284 + } 285 + 286 + if (iattr->ia_valid & ATTR_ATIME) 287 + info.access_time.ns_relative_to_unix_epoch = 288 + timespec64_to_ns(&iattr->ia_atime); 289 + 290 + if (iattr->ia_valid & ATTR_MTIME) 291 + info.modification_time.ns_relative_to_unix_epoch = 292 + timespec64_to_ns(&iattr->ia_mtime); 293 + 294 + /* 295 + * Ignore ctime (inode change time) as it can't be set 296 + * from userland anyway. 297 + */ 298 + 299 + buf_len = sizeof(info); 300 + err = vboxsf_fsinfo(sbi->root, params.handle, 301 + SHFL_INFO_SET | SHFL_INFO_FILE, &buf_len, 302 + &info); 303 + if (err) { 304 + vboxsf_close(sbi->root, params.handle); 305 + return err; 306 + } 307 + 308 + /* the host may have given us different attr then requested */ 309 + sf_i->force_restat = 1; 310 + } 311 + 312 + #undef mode_set 313 + 314 + if (iattr->ia_valid & ATTR_SIZE) { 315 + memset(&info, 0, sizeof(info)); 316 + info.size = iattr->ia_size; 317 + buf_len = sizeof(info); 318 + err = vboxsf_fsinfo(sbi->root, params.handle, 319 + SHFL_INFO_SET | SHFL_INFO_SIZE, &buf_len, 320 + &info); 321 + if (err) { 322 + vboxsf_close(sbi->root, params.handle); 323 + return err; 324 + } 325 + 326 + /* the host may have given us different attr then requested */ 327 + sf_i->force_restat = 1; 328 + } 329 + 330 + vboxsf_close(sbi->root, params.handle); 331 + 332 + /* Update the inode with what the host has actually given us. */ 333 + if (sf_i->force_restat) 334 + vboxsf_inode_revalidate(dentry); 335 + 336 + return 0; 337 + } 338 + 339 + /* 340 + * [dentry] contains string encoded in coding system that corresponds 341 + * to [sbi]->nls, we must convert it to UTF8 here. 342 + * Returns a shfl_string allocated through __getname (must be freed using 343 + * __putname), or an ERR_PTR on error. 344 + */ 345 + struct shfl_string *vboxsf_path_from_dentry(struct vboxsf_sbi *sbi, 346 + struct dentry *dentry) 347 + { 348 + struct shfl_string *shfl_path; 349 + int path_len, out_len, nb; 350 + char *buf, *path; 351 + wchar_t uni; 352 + u8 *out; 353 + 354 + buf = __getname(); 355 + if (!buf) 356 + return ERR_PTR(-ENOMEM); 357 + 358 + path = dentry_path_raw(dentry, buf, PATH_MAX); 359 + if (IS_ERR(path)) { 360 + __putname(buf); 361 + return ERR_CAST(path); 362 + } 363 + path_len = strlen(path); 364 + 365 + if (sbi->nls) { 366 + shfl_path = __getname(); 367 + if (!shfl_path) { 368 + __putname(buf); 369 + return ERR_PTR(-ENOMEM); 370 + } 371 + 372 + out = shfl_path->string.utf8; 373 + out_len = PATH_MAX - SHFLSTRING_HEADER_SIZE - 1; 374 + 375 + while (path_len) { 376 + nb = sbi->nls->char2uni(path, path_len, &uni); 377 + if (nb < 0) { 378 + __putname(shfl_path); 379 + __putname(buf); 380 + return ERR_PTR(-EINVAL); 381 + } 382 + path += nb; 383 + path_len -= nb; 384 + 385 + nb = utf32_to_utf8(uni, out, out_len); 386 + if (nb < 0) { 387 + __putname(shfl_path); 388 + __putname(buf); 389 + return ERR_PTR(-ENAMETOOLONG); 390 + } 391 + out += nb; 392 + out_len -= nb; 393 + } 394 + *out = 0; 395 + shfl_path->length = out - shfl_path->string.utf8; 396 + shfl_path->size = shfl_path->length + 1; 397 + __putname(buf); 398 + } else { 399 + if ((SHFLSTRING_HEADER_SIZE + path_len + 1) > PATH_MAX) { 400 + __putname(buf); 401 + return ERR_PTR(-ENAMETOOLONG); 402 + } 403 + /* 404 + * dentry_path stores the name at the end of buf, but the 405 + * shfl_string string we return must be properly aligned. 406 + */ 407 + shfl_path = (struct shfl_string *)buf; 408 + memmove(shfl_path->string.utf8, path, path_len); 409 + shfl_path->string.utf8[path_len] = 0; 410 + shfl_path->length = path_len; 411 + shfl_path->size = path_len + 1; 412 + } 413 + 414 + return shfl_path; 415 + } 416 + 417 + int vboxsf_nlscpy(struct vboxsf_sbi *sbi, char *name, size_t name_bound_len, 418 + const unsigned char *utf8_name, size_t utf8_len) 419 + { 420 + const char *in; 421 + char *out; 422 + size_t out_len; 423 + size_t out_bound_len; 424 + size_t in_bound_len; 425 + 426 + in = utf8_name; 427 + in_bound_len = utf8_len; 428 + 429 + out = name; 430 + out_len = 0; 431 + /* Reserve space for terminating 0 */ 432 + out_bound_len = name_bound_len - 1; 433 + 434 + while (in_bound_len) { 435 + int nb; 436 + unicode_t uni; 437 + 438 + nb = utf8_to_utf32(in, in_bound_len, &uni); 439 + if (nb < 0) 440 + return -EINVAL; 441 + 442 + in += nb; 443 + in_bound_len -= nb; 444 + 445 + nb = sbi->nls->uni2char(uni, out, out_bound_len); 446 + if (nb < 0) 447 + return nb; 448 + 449 + out += nb; 450 + out_bound_len -= nb; 451 + out_len += nb; 452 + } 453 + 454 + *out = 0; 455 + 456 + return 0; 457 + } 458 + 459 + static struct vboxsf_dir_buf *vboxsf_dir_buf_alloc(struct list_head *list) 460 + { 461 + struct vboxsf_dir_buf *b; 462 + 463 + b = kmalloc(sizeof(*b), GFP_KERNEL); 464 + if (!b) 465 + return NULL; 466 + 467 + b->buf = kmalloc(DIR_BUFFER_SIZE, GFP_KERNEL); 468 + if (!b->buf) { 469 + kfree(b); 470 + return NULL; 471 + } 472 + 473 + b->entries = 0; 474 + b->used = 0; 475 + b->free = DIR_BUFFER_SIZE; 476 + list_add(&b->head, list); 477 + 478 + return b; 479 + } 480 + 481 + static void vboxsf_dir_buf_free(struct vboxsf_dir_buf *b) 482 + { 483 + list_del(&b->head); 484 + kfree(b->buf); 485 + kfree(b); 486 + } 487 + 488 + struct vboxsf_dir_info *vboxsf_dir_info_alloc(void) 489 + { 490 + struct vboxsf_dir_info *p; 491 + 492 + p = kmalloc(sizeof(*p), GFP_KERNEL); 493 + if (!p) 494 + return NULL; 495 + 496 + INIT_LIST_HEAD(&p->info_list); 497 + return p; 498 + } 499 + 500 + void vboxsf_dir_info_free(struct vboxsf_dir_info *p) 501 + { 502 + struct list_head *list, *pos, *tmp; 503 + 504 + list = &p->info_list; 505 + list_for_each_safe(pos, tmp, list) { 506 + struct vboxsf_dir_buf *b; 507 + 508 + b = list_entry(pos, struct vboxsf_dir_buf, head); 509 + vboxsf_dir_buf_free(b); 510 + } 511 + kfree(p); 512 + } 513 + 514 + int vboxsf_dir_read_all(struct vboxsf_sbi *sbi, struct vboxsf_dir_info *sf_d, 515 + u64 handle) 516 + { 517 + struct vboxsf_dir_buf *b; 518 + u32 entries, size; 519 + int err = 0; 520 + void *buf; 521 + 522 + /* vboxsf_dirinfo returns 1 on end of dir */ 523 + while (err == 0) { 524 + b = vboxsf_dir_buf_alloc(&sf_d->info_list); 525 + if (!b) { 526 + err = -ENOMEM; 527 + break; 528 + } 529 + 530 + buf = b->buf; 531 + size = b->free; 532 + 533 + err = vboxsf_dirinfo(sbi->root, handle, NULL, 0, 0, 534 + &size, buf, &entries); 535 + if (err < 0) 536 + break; 537 + 538 + b->entries += entries; 539 + b->free -= size; 540 + b->used += size; 541 + } 542 + 543 + if (b && b->used == 0) 544 + vboxsf_dir_buf_free(b); 545 + 546 + /* -EILSEQ means the host could not translate a filename, ignore */ 547 + if (err > 0 || err == -EILSEQ) 548 + err = 0; 549 + 550 + return err; 551 + }
+371
fs/vboxsf/vboxsf_wrappers.c
··· 1 + // SPDX-License-Identifier: MIT 2 + /* 3 + * Wrapper functions for the shfl host calls. 4 + * 5 + * Copyright (C) 2006-2018 Oracle Corporation 6 + */ 7 + 8 + #include <linux/mm.h> 9 + #include <linux/slab.h> 10 + #include <linux/vbox_err.h> 11 + #include <linux/vbox_utils.h> 12 + #include "vfsmod.h" 13 + 14 + #define SHFL_REQUEST \ 15 + (VMMDEV_REQUESTOR_KERNEL | VMMDEV_REQUESTOR_USR_DRV_OTHER | \ 16 + VMMDEV_REQUESTOR_CON_DONT_KNOW | VMMDEV_REQUESTOR_TRUST_NOT_GIVEN) 17 + 18 + static u32 vboxsf_client_id; 19 + 20 + int vboxsf_connect(void) 21 + { 22 + struct vbg_dev *gdev; 23 + struct vmmdev_hgcm_service_location loc; 24 + int err, vbox_status; 25 + 26 + loc.type = VMMDEV_HGCM_LOC_LOCALHOST_EXISTING; 27 + strcpy(loc.u.localhost.service_name, "VBoxSharedFolders"); 28 + 29 + gdev = vbg_get_gdev(); 30 + if (IS_ERR(gdev)) 31 + return -ENODEV; /* No guest-device */ 32 + 33 + err = vbg_hgcm_connect(gdev, SHFL_REQUEST, &loc, 34 + &vboxsf_client_id, &vbox_status); 35 + vbg_put_gdev(gdev); 36 + 37 + return err ? err : vbg_status_code_to_errno(vbox_status); 38 + } 39 + 40 + void vboxsf_disconnect(void) 41 + { 42 + struct vbg_dev *gdev; 43 + int vbox_status; 44 + 45 + gdev = vbg_get_gdev(); 46 + if (IS_ERR(gdev)) 47 + return; /* guest-device is gone, already disconnected */ 48 + 49 + vbg_hgcm_disconnect(gdev, SHFL_REQUEST, vboxsf_client_id, &vbox_status); 50 + vbg_put_gdev(gdev); 51 + } 52 + 53 + static int vboxsf_call(u32 function, void *parms, u32 parm_count, int *status) 54 + { 55 + struct vbg_dev *gdev; 56 + int err, vbox_status; 57 + 58 + gdev = vbg_get_gdev(); 59 + if (IS_ERR(gdev)) 60 + return -ESHUTDOWN; /* guest-dev removed underneath us */ 61 + 62 + err = vbg_hgcm_call(gdev, SHFL_REQUEST, vboxsf_client_id, function, 63 + U32_MAX, parms, parm_count, &vbox_status); 64 + vbg_put_gdev(gdev); 65 + 66 + if (err < 0) 67 + return err; 68 + 69 + if (status) 70 + *status = vbox_status; 71 + 72 + return vbg_status_code_to_errno(vbox_status); 73 + } 74 + 75 + int vboxsf_map_folder(struct shfl_string *folder_name, u32 *root) 76 + { 77 + struct shfl_map_folder parms; 78 + int err, status; 79 + 80 + parms.path.type = VMMDEV_HGCM_PARM_TYPE_LINADDR_KERNEL; 81 + parms.path.u.pointer.size = shfl_string_buf_size(folder_name); 82 + parms.path.u.pointer.u.linear_addr = (uintptr_t)folder_name; 83 + 84 + parms.root.type = VMMDEV_HGCM_PARM_TYPE_32BIT; 85 + parms.root.u.value32 = 0; 86 + 87 + parms.delimiter.type = VMMDEV_HGCM_PARM_TYPE_32BIT; 88 + parms.delimiter.u.value32 = '/'; 89 + 90 + parms.case_sensitive.type = VMMDEV_HGCM_PARM_TYPE_32BIT; 91 + parms.case_sensitive.u.value32 = 1; 92 + 93 + err = vboxsf_call(SHFL_FN_MAP_FOLDER, &parms, SHFL_CPARMS_MAP_FOLDER, 94 + &status); 95 + if (err == -ENOSYS && status == VERR_NOT_IMPLEMENTED) 96 + vbg_err("%s: Error host is too old\n", __func__); 97 + 98 + *root = parms.root.u.value32; 99 + return err; 100 + } 101 + 102 + int vboxsf_unmap_folder(u32 root) 103 + { 104 + struct shfl_unmap_folder parms; 105 + 106 + parms.root.type = VMMDEV_HGCM_PARM_TYPE_32BIT; 107 + parms.root.u.value32 = root; 108 + 109 + return vboxsf_call(SHFL_FN_UNMAP_FOLDER, &parms, 110 + SHFL_CPARMS_UNMAP_FOLDER, NULL); 111 + } 112 + 113 + /** 114 + * vboxsf_create - Create a new file or folder 115 + * @root: Root of the shared folder in which to create the file 116 + * @parsed_path: The path of the file or folder relative to the shared folder 117 + * @param: create_parms Parameters for file/folder creation. 118 + * 119 + * Create a new file or folder or open an existing one in a shared folder. 120 + * Note this function always returns 0 / success unless an exceptional condition 121 + * occurs - out of memory, invalid arguments, etc. If the file or folder could 122 + * not be opened or created, create_parms->handle will be set to 123 + * SHFL_HANDLE_NIL on return. In this case the value in create_parms->result 124 + * provides information as to why (e.g. SHFL_FILE_EXISTS), create_parms->result 125 + * is also set on success as additional information. 126 + * 127 + * Returns: 128 + * 0 or negative errno value. 129 + */ 130 + int vboxsf_create(u32 root, struct shfl_string *parsed_path, 131 + struct shfl_createparms *create_parms) 132 + { 133 + struct shfl_create parms; 134 + 135 + parms.root.type = VMMDEV_HGCM_PARM_TYPE_32BIT; 136 + parms.root.u.value32 = root; 137 + 138 + parms.path.type = VMMDEV_HGCM_PARM_TYPE_LINADDR_KERNEL; 139 + parms.path.u.pointer.size = shfl_string_buf_size(parsed_path); 140 + parms.path.u.pointer.u.linear_addr = (uintptr_t)parsed_path; 141 + 142 + parms.parms.type = VMMDEV_HGCM_PARM_TYPE_LINADDR_KERNEL; 143 + parms.parms.u.pointer.size = sizeof(struct shfl_createparms); 144 + parms.parms.u.pointer.u.linear_addr = (uintptr_t)create_parms; 145 + 146 + return vboxsf_call(SHFL_FN_CREATE, &parms, SHFL_CPARMS_CREATE, NULL); 147 + } 148 + 149 + int vboxsf_close(u32 root, u64 handle) 150 + { 151 + struct shfl_close parms; 152 + 153 + parms.root.type = VMMDEV_HGCM_PARM_TYPE_32BIT; 154 + parms.root.u.value32 = root; 155 + 156 + parms.handle.type = VMMDEV_HGCM_PARM_TYPE_64BIT; 157 + parms.handle.u.value64 = handle; 158 + 159 + return vboxsf_call(SHFL_FN_CLOSE, &parms, SHFL_CPARMS_CLOSE, NULL); 160 + } 161 + 162 + int vboxsf_remove(u32 root, struct shfl_string *parsed_path, u32 flags) 163 + { 164 + struct shfl_remove parms; 165 + 166 + parms.root.type = VMMDEV_HGCM_PARM_TYPE_32BIT; 167 + parms.root.u.value32 = root; 168 + 169 + parms.path.type = VMMDEV_HGCM_PARM_TYPE_LINADDR_KERNEL_IN; 170 + parms.path.u.pointer.size = shfl_string_buf_size(parsed_path); 171 + parms.path.u.pointer.u.linear_addr = (uintptr_t)parsed_path; 172 + 173 + parms.flags.type = VMMDEV_HGCM_PARM_TYPE_32BIT; 174 + parms.flags.u.value32 = flags; 175 + 176 + return vboxsf_call(SHFL_FN_REMOVE, &parms, SHFL_CPARMS_REMOVE, NULL); 177 + } 178 + 179 + int vboxsf_rename(u32 root, struct shfl_string *src_path, 180 + struct shfl_string *dest_path, u32 flags) 181 + { 182 + struct shfl_rename parms; 183 + 184 + parms.root.type = VMMDEV_HGCM_PARM_TYPE_32BIT; 185 + parms.root.u.value32 = root; 186 + 187 + parms.src.type = VMMDEV_HGCM_PARM_TYPE_LINADDR_KERNEL_IN; 188 + parms.src.u.pointer.size = shfl_string_buf_size(src_path); 189 + parms.src.u.pointer.u.linear_addr = (uintptr_t)src_path; 190 + 191 + parms.dest.type = VMMDEV_HGCM_PARM_TYPE_LINADDR_KERNEL_IN; 192 + parms.dest.u.pointer.size = shfl_string_buf_size(dest_path); 193 + parms.dest.u.pointer.u.linear_addr = (uintptr_t)dest_path; 194 + 195 + parms.flags.type = VMMDEV_HGCM_PARM_TYPE_32BIT; 196 + parms.flags.u.value32 = flags; 197 + 198 + return vboxsf_call(SHFL_FN_RENAME, &parms, SHFL_CPARMS_RENAME, NULL); 199 + } 200 + 201 + int vboxsf_read(u32 root, u64 handle, u64 offset, u32 *buf_len, u8 *buf) 202 + { 203 + struct shfl_read parms; 204 + int err; 205 + 206 + parms.root.type = VMMDEV_HGCM_PARM_TYPE_32BIT; 207 + parms.root.u.value32 = root; 208 + 209 + parms.handle.type = VMMDEV_HGCM_PARM_TYPE_64BIT; 210 + parms.handle.u.value64 = handle; 211 + parms.offset.type = VMMDEV_HGCM_PARM_TYPE_64BIT; 212 + parms.offset.u.value64 = offset; 213 + parms.cb.type = VMMDEV_HGCM_PARM_TYPE_32BIT; 214 + parms.cb.u.value32 = *buf_len; 215 + parms.buffer.type = VMMDEV_HGCM_PARM_TYPE_LINADDR_KERNEL_OUT; 216 + parms.buffer.u.pointer.size = *buf_len; 217 + parms.buffer.u.pointer.u.linear_addr = (uintptr_t)buf; 218 + 219 + err = vboxsf_call(SHFL_FN_READ, &parms, SHFL_CPARMS_READ, NULL); 220 + 221 + *buf_len = parms.cb.u.value32; 222 + return err; 223 + } 224 + 225 + int vboxsf_write(u32 root, u64 handle, u64 offset, u32 *buf_len, u8 *buf) 226 + { 227 + struct shfl_write parms; 228 + int err; 229 + 230 + parms.root.type = VMMDEV_HGCM_PARM_TYPE_32BIT; 231 + parms.root.u.value32 = root; 232 + 233 + parms.handle.type = VMMDEV_HGCM_PARM_TYPE_64BIT; 234 + parms.handle.u.value64 = handle; 235 + parms.offset.type = VMMDEV_HGCM_PARM_TYPE_64BIT; 236 + parms.offset.u.value64 = offset; 237 + parms.cb.type = VMMDEV_HGCM_PARM_TYPE_32BIT; 238 + parms.cb.u.value32 = *buf_len; 239 + parms.buffer.type = VMMDEV_HGCM_PARM_TYPE_LINADDR_KERNEL_IN; 240 + parms.buffer.u.pointer.size = *buf_len; 241 + parms.buffer.u.pointer.u.linear_addr = (uintptr_t)buf; 242 + 243 + err = vboxsf_call(SHFL_FN_WRITE, &parms, SHFL_CPARMS_WRITE, NULL); 244 + 245 + *buf_len = parms.cb.u.value32; 246 + return err; 247 + } 248 + 249 + /* Returns 0 on success, 1 on end-of-dir, negative errno otherwise */ 250 + int vboxsf_dirinfo(u32 root, u64 handle, 251 + struct shfl_string *parsed_path, u32 flags, u32 index, 252 + u32 *buf_len, struct shfl_dirinfo *buf, u32 *file_count) 253 + { 254 + struct shfl_list parms; 255 + int err, status; 256 + 257 + parms.root.type = VMMDEV_HGCM_PARM_TYPE_32BIT; 258 + parms.root.u.value32 = root; 259 + 260 + parms.handle.type = VMMDEV_HGCM_PARM_TYPE_64BIT; 261 + parms.handle.u.value64 = handle; 262 + parms.flags.type = VMMDEV_HGCM_PARM_TYPE_32BIT; 263 + parms.flags.u.value32 = flags; 264 + parms.cb.type = VMMDEV_HGCM_PARM_TYPE_32BIT; 265 + parms.cb.u.value32 = *buf_len; 266 + if (parsed_path) { 267 + parms.path.type = VMMDEV_HGCM_PARM_TYPE_LINADDR_KERNEL_IN; 268 + parms.path.u.pointer.size = shfl_string_buf_size(parsed_path); 269 + parms.path.u.pointer.u.linear_addr = (uintptr_t)parsed_path; 270 + } else { 271 + parms.path.type = VMMDEV_HGCM_PARM_TYPE_LINADDR_IN; 272 + parms.path.u.pointer.size = 0; 273 + parms.path.u.pointer.u.linear_addr = 0; 274 + } 275 + 276 + parms.buffer.type = VMMDEV_HGCM_PARM_TYPE_LINADDR_KERNEL_OUT; 277 + parms.buffer.u.pointer.size = *buf_len; 278 + parms.buffer.u.pointer.u.linear_addr = (uintptr_t)buf; 279 + 280 + parms.resume_point.type = VMMDEV_HGCM_PARM_TYPE_32BIT; 281 + parms.resume_point.u.value32 = index; 282 + parms.file_count.type = VMMDEV_HGCM_PARM_TYPE_32BIT; 283 + parms.file_count.u.value32 = 0; /* out parameter only */ 284 + 285 + err = vboxsf_call(SHFL_FN_LIST, &parms, SHFL_CPARMS_LIST, &status); 286 + if (err == -ENODATA && status == VERR_NO_MORE_FILES) 287 + err = 1; 288 + 289 + *buf_len = parms.cb.u.value32; 290 + *file_count = parms.file_count.u.value32; 291 + return err; 292 + } 293 + 294 + int vboxsf_fsinfo(u32 root, u64 handle, u32 flags, 295 + u32 *buf_len, void *buf) 296 + { 297 + struct shfl_information parms; 298 + int err; 299 + 300 + parms.root.type = VMMDEV_HGCM_PARM_TYPE_32BIT; 301 + parms.root.u.value32 = root; 302 + 303 + parms.handle.type = VMMDEV_HGCM_PARM_TYPE_64BIT; 304 + parms.handle.u.value64 = handle; 305 + parms.flags.type = VMMDEV_HGCM_PARM_TYPE_32BIT; 306 + parms.flags.u.value32 = flags; 307 + parms.cb.type = VMMDEV_HGCM_PARM_TYPE_32BIT; 308 + parms.cb.u.value32 = *buf_len; 309 + parms.info.type = VMMDEV_HGCM_PARM_TYPE_LINADDR_KERNEL; 310 + parms.info.u.pointer.size = *buf_len; 311 + parms.info.u.pointer.u.linear_addr = (uintptr_t)buf; 312 + 313 + err = vboxsf_call(SHFL_FN_INFORMATION, &parms, SHFL_CPARMS_INFORMATION, 314 + NULL); 315 + 316 + *buf_len = parms.cb.u.value32; 317 + return err; 318 + } 319 + 320 + int vboxsf_readlink(u32 root, struct shfl_string *parsed_path, 321 + u32 buf_len, u8 *buf) 322 + { 323 + struct shfl_readLink parms; 324 + 325 + parms.root.type = VMMDEV_HGCM_PARM_TYPE_32BIT; 326 + parms.root.u.value32 = root; 327 + 328 + parms.path.type = VMMDEV_HGCM_PARM_TYPE_LINADDR_KERNEL_IN; 329 + parms.path.u.pointer.size = shfl_string_buf_size(parsed_path); 330 + parms.path.u.pointer.u.linear_addr = (uintptr_t)parsed_path; 331 + 332 + parms.buffer.type = VMMDEV_HGCM_PARM_TYPE_LINADDR_KERNEL_OUT; 333 + parms.buffer.u.pointer.size = buf_len; 334 + parms.buffer.u.pointer.u.linear_addr = (uintptr_t)buf; 335 + 336 + return vboxsf_call(SHFL_FN_READLINK, &parms, SHFL_CPARMS_READLINK, 337 + NULL); 338 + } 339 + 340 + int vboxsf_symlink(u32 root, struct shfl_string *new_path, 341 + struct shfl_string *old_path, struct shfl_fsobjinfo *buf) 342 + { 343 + struct shfl_symlink parms; 344 + 345 + parms.root.type = VMMDEV_HGCM_PARM_TYPE_32BIT; 346 + parms.root.u.value32 = root; 347 + 348 + parms.new_path.type = VMMDEV_HGCM_PARM_TYPE_LINADDR_KERNEL_IN; 349 + parms.new_path.u.pointer.size = shfl_string_buf_size(new_path); 350 + parms.new_path.u.pointer.u.linear_addr = (uintptr_t)new_path; 351 + 352 + parms.old_path.type = VMMDEV_HGCM_PARM_TYPE_LINADDR_KERNEL_IN; 353 + parms.old_path.u.pointer.size = shfl_string_buf_size(old_path); 354 + parms.old_path.u.pointer.u.linear_addr = (uintptr_t)old_path; 355 + 356 + parms.info.type = VMMDEV_HGCM_PARM_TYPE_LINADDR_KERNEL_OUT; 357 + parms.info.u.pointer.size = sizeof(struct shfl_fsobjinfo); 358 + parms.info.u.pointer.u.linear_addr = (uintptr_t)buf; 359 + 360 + return vboxsf_call(SHFL_FN_SYMLINK, &parms, SHFL_CPARMS_SYMLINK, NULL); 361 + } 362 + 363 + int vboxsf_set_utf8(void) 364 + { 365 + return vboxsf_call(SHFL_FN_SET_UTF8, NULL, 0, NULL); 366 + } 367 + 368 + int vboxsf_set_symlinks(void) 369 + { 370 + return vboxsf_call(SHFL_FN_SET_SYMLINKS, NULL, 0, NULL); 371 + }
+137
fs/vboxsf/vfsmod.h
··· 1 + /* SPDX-License-Identifier: MIT */ 2 + /* 3 + * VirtualBox Guest Shared Folders support: module header. 4 + * 5 + * Copyright (C) 2006-2018 Oracle Corporation 6 + */ 7 + 8 + #ifndef VFSMOD_H 9 + #define VFSMOD_H 10 + 11 + #include <linux/backing-dev.h> 12 + #include <linux/idr.h> 13 + #include "shfl_hostintf.h" 14 + 15 + #define DIR_BUFFER_SIZE SZ_16K 16 + 17 + /* The cast is to prevent assignment of void * to pointers of arbitrary type */ 18 + #define VBOXSF_SBI(sb) ((struct vboxsf_sbi *)(sb)->s_fs_info) 19 + #define VBOXSF_I(i) container_of(i, struct vboxsf_inode, vfs_inode) 20 + 21 + struct vboxsf_options { 22 + unsigned long ttl; 23 + kuid_t uid; 24 + kgid_t gid; 25 + bool dmode_set; 26 + bool fmode_set; 27 + umode_t dmode; 28 + umode_t fmode; 29 + umode_t dmask; 30 + umode_t fmask; 31 + }; 32 + 33 + struct vboxsf_fs_context { 34 + struct vboxsf_options o; 35 + char *nls_name; 36 + }; 37 + 38 + /* per-shared folder information */ 39 + struct vboxsf_sbi { 40 + struct vboxsf_options o; 41 + struct shfl_fsobjinfo root_info; 42 + struct idr ino_idr; 43 + spinlock_t ino_idr_lock; /* This protects ino_idr */ 44 + struct nls_table *nls; 45 + u32 next_generation; 46 + u32 root; 47 + int bdi_id; 48 + }; 49 + 50 + /* per-inode information */ 51 + struct vboxsf_inode { 52 + /* some information was changed, update data on next revalidate */ 53 + int force_restat; 54 + /* list of open handles for this inode + lock protecting it */ 55 + struct list_head handle_list; 56 + /* This mutex protects handle_list accesses */ 57 + struct mutex handle_list_mutex; 58 + /* The VFS inode struct */ 59 + struct inode vfs_inode; 60 + }; 61 + 62 + struct vboxsf_dir_info { 63 + struct list_head info_list; 64 + }; 65 + 66 + struct vboxsf_dir_buf { 67 + size_t entries; 68 + size_t free; 69 + size_t used; 70 + void *buf; 71 + struct list_head head; 72 + }; 73 + 74 + /* globals */ 75 + extern const struct inode_operations vboxsf_dir_iops; 76 + extern const struct inode_operations vboxsf_lnk_iops; 77 + extern const struct inode_operations vboxsf_reg_iops; 78 + extern const struct file_operations vboxsf_dir_fops; 79 + extern const struct file_operations vboxsf_reg_fops; 80 + extern const struct address_space_operations vboxsf_reg_aops; 81 + extern const struct dentry_operations vboxsf_dentry_ops; 82 + 83 + /* from utils.c */ 84 + struct inode *vboxsf_new_inode(struct super_block *sb); 85 + void vboxsf_init_inode(struct vboxsf_sbi *sbi, struct inode *inode, 86 + const struct shfl_fsobjinfo *info); 87 + int vboxsf_create_at_dentry(struct dentry *dentry, 88 + struct shfl_createparms *params); 89 + int vboxsf_stat(struct vboxsf_sbi *sbi, struct shfl_string *path, 90 + struct shfl_fsobjinfo *info); 91 + int vboxsf_stat_dentry(struct dentry *dentry, struct shfl_fsobjinfo *info); 92 + int vboxsf_inode_revalidate(struct dentry *dentry); 93 + int vboxsf_getattr(const struct path *path, struct kstat *kstat, 94 + u32 request_mask, unsigned int query_flags); 95 + int vboxsf_setattr(struct dentry *dentry, struct iattr *iattr); 96 + struct shfl_string *vboxsf_path_from_dentry(struct vboxsf_sbi *sbi, 97 + struct dentry *dentry); 98 + int vboxsf_nlscpy(struct vboxsf_sbi *sbi, char *name, size_t name_bound_len, 99 + const unsigned char *utf8_name, size_t utf8_len); 100 + struct vboxsf_dir_info *vboxsf_dir_info_alloc(void); 101 + void vboxsf_dir_info_free(struct vboxsf_dir_info *p); 102 + int vboxsf_dir_read_all(struct vboxsf_sbi *sbi, struct vboxsf_dir_info *sf_d, 103 + u64 handle); 104 + 105 + /* from vboxsf_wrappers.c */ 106 + int vboxsf_connect(void); 107 + void vboxsf_disconnect(void); 108 + 109 + int vboxsf_create(u32 root, struct shfl_string *parsed_path, 110 + struct shfl_createparms *create_parms); 111 + 112 + int vboxsf_close(u32 root, u64 handle); 113 + int vboxsf_remove(u32 root, struct shfl_string *parsed_path, u32 flags); 114 + int vboxsf_rename(u32 root, struct shfl_string *src_path, 115 + struct shfl_string *dest_path, u32 flags); 116 + 117 + int vboxsf_read(u32 root, u64 handle, u64 offset, u32 *buf_len, u8 *buf); 118 + int vboxsf_write(u32 root, u64 handle, u64 offset, u32 *buf_len, u8 *buf); 119 + 120 + int vboxsf_dirinfo(u32 root, u64 handle, 121 + struct shfl_string *parsed_path, u32 flags, u32 index, 122 + u32 *buf_len, struct shfl_dirinfo *buf, u32 *file_count); 123 + int vboxsf_fsinfo(u32 root, u64 handle, u32 flags, 124 + u32 *buf_len, void *buf); 125 + 126 + int vboxsf_map_folder(struct shfl_string *folder_name, u32 *root); 127 + int vboxsf_unmap_folder(u32 root); 128 + 129 + int vboxsf_readlink(u32 root, struct shfl_string *parsed_path, 130 + u32 buf_len, u8 *buf); 131 + int vboxsf_symlink(u32 root, struct shfl_string *new_path, 132 + struct shfl_string *old_path, struct shfl_fsobjinfo *buf); 133 + 134 + int vboxsf_set_utf8(void); 135 + int vboxsf_set_symlinks(void); 136 + 137 + #endif