From 0e3f1ad80fc8cb0c517fd9a9afb22752b741fa76 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Tue, 12 Nov 2019 15:22:24 -0800 Subject: Remove VirtualBox guest shared folders filesystem This went into staging in rc7. It turns out that was a mistake, and apparently it wasn't even supposed to go there at all, but be introduced as a regular filesystem. We don't try to sneak in whole new filesystems this late in the rc, just delete the whole thing, and it can be re-introduced as a proper patch with proper acks from actual filesystem people instead of some odd late-rc staging back-door. Cc: Greg Kroah-Hartman Cc: Christoph Hellwig Cc: Hans de Goede Signed-off-by: Linus Torvalds --- drivers/staging/Kconfig | 2 - drivers/staging/Makefile | 1 - drivers/staging/vboxsf/Kconfig | 10 - drivers/staging/vboxsf/Makefile | 5 - drivers/staging/vboxsf/TODO | 7 - drivers/staging/vboxsf/dir.c | 418 -------------- drivers/staging/vboxsf/file.c | 370 ------------- drivers/staging/vboxsf/shfl_hostintf.h | 901 ------------------------------- drivers/staging/vboxsf/super.c | 501 ----------------- drivers/staging/vboxsf/utils.c | 551 ------------------- drivers/staging/vboxsf/vboxsf_wrappers.c | 371 ------------- drivers/staging/vboxsf/vfsmod.h | 137 ----- 12 files changed, 3274 deletions(-) delete mode 100644 drivers/staging/vboxsf/Kconfig delete mode 100644 drivers/staging/vboxsf/Makefile delete mode 100644 drivers/staging/vboxsf/TODO delete mode 100644 drivers/staging/vboxsf/dir.c delete mode 100644 drivers/staging/vboxsf/file.c delete mode 100644 drivers/staging/vboxsf/shfl_hostintf.h delete mode 100644 drivers/staging/vboxsf/super.c delete mode 100644 drivers/staging/vboxsf/utils.c delete mode 100644 drivers/staging/vboxsf/vboxsf_wrappers.c delete mode 100644 drivers/staging/vboxsf/vfsmod.h (limited to 'drivers/staging') diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig index 927d29eb92c6..6f1fa4c849a1 100644 --- a/drivers/staging/Kconfig +++ b/drivers/staging/Kconfig @@ -125,6 +125,4 @@ source "drivers/staging/exfat/Kconfig" source "drivers/staging/qlge/Kconfig" -source "drivers/staging/vboxsf/Kconfig" - endif # STAGING diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile index f01f04199073..a90f9b308c8d 100644 --- a/drivers/staging/Makefile +++ b/drivers/staging/Makefile @@ -53,4 +53,3 @@ obj-$(CONFIG_UWB) += uwb/ obj-$(CONFIG_USB_WUSB) += wusbcore/ obj-$(CONFIG_EXFAT_FS) += exfat/ obj-$(CONFIG_QLGE) += qlge/ -obj-$(CONFIG_VBOXSF_FS) += vboxsf/ diff --git a/drivers/staging/vboxsf/Kconfig b/drivers/staging/vboxsf/Kconfig deleted file mode 100644 index b84586ae08b3..000000000000 --- a/drivers/staging/vboxsf/Kconfig +++ /dev/null @@ -1,10 +0,0 @@ -config VBOXSF_FS - tristate "VirtualBox guest shared folder (vboxsf) support" - depends on X86 && VBOXGUEST - select NLS - help - VirtualBox hosts can share folders with guests, this driver - implements the Linux-guest side of this allowing folders exported - by the host to be mounted under Linux. - - If you want to use shared folders in VirtualBox guests, answer Y or M. diff --git a/drivers/staging/vboxsf/Makefile b/drivers/staging/vboxsf/Makefile deleted file mode 100644 index 9e4328e79623..000000000000 --- a/drivers/staging/vboxsf/Makefile +++ /dev/null @@ -1,5 +0,0 @@ -# SPDX-License-Identifier: MIT - -obj-$(CONFIG_VBOXSF_FS) += vboxsf.o - -vboxsf-y := dir.o file.o utils.o vboxsf_wrappers.o super.o diff --git a/drivers/staging/vboxsf/TODO b/drivers/staging/vboxsf/TODO deleted file mode 100644 index 8b9193d0d4f0..000000000000 --- a/drivers/staging/vboxsf/TODO +++ /dev/null @@ -1,7 +0,0 @@ -TODO: -- Find a file-system developer to review this and give their Reviewed-By -- Address any items coming up during review -- Move to fs/vboxfs - -Please send any patches to Greg Kroah-Hartman -and Hans de Goede diff --git a/drivers/staging/vboxsf/dir.c b/drivers/staging/vboxsf/dir.c deleted file mode 100644 index f260b5cc1646..000000000000 --- a/drivers/staging/vboxsf/dir.c +++ /dev/null @@ -1,418 +0,0 @@ -// SPDX-License-Identifier: MIT -/* - * VirtualBox Guest Shared Folders support: Directory inode and file operations - * - * Copyright (C) 2006-2018 Oracle Corporation - */ - -#include -#include -#include "vfsmod.h" - -static int vboxsf_dir_open(struct inode *inode, struct file *file) -{ - struct vboxsf_sbi *sbi = VBOXSF_SBI(inode->i_sb); - struct shfl_createparms params = {}; - struct vboxsf_dir_info *sf_d; - int err; - - sf_d = vboxsf_dir_info_alloc(); - if (!sf_d) - return -ENOMEM; - - params.handle = SHFL_HANDLE_NIL; - params.create_flags = SHFL_CF_DIRECTORY | SHFL_CF_ACT_OPEN_IF_EXISTS | - SHFL_CF_ACT_FAIL_IF_NEW | SHFL_CF_ACCESS_READ; - - err = vboxsf_create_at_dentry(file_dentry(file), ¶ms); - if (err) - goto err_free_dir_info; - - if (params.result != SHFL_FILE_EXISTS) { - err = -ENOENT; - goto err_close; - } - - err = vboxsf_dir_read_all(sbi, sf_d, params.handle); - if (err) - goto err_close; - - vboxsf_close(sbi->root, params.handle); - file->private_data = sf_d; - return 0; - -err_close: - vboxsf_close(sbi->root, params.handle); -err_free_dir_info: - vboxsf_dir_info_free(sf_d); - return err; -} - -static int vboxsf_dir_release(struct inode *inode, struct file *file) -{ - if (file->private_data) - vboxsf_dir_info_free(file->private_data); - - return 0; -} - -static unsigned int vboxsf_get_d_type(u32 mode) -{ - unsigned int d_type; - - switch (mode & SHFL_TYPE_MASK) { - case SHFL_TYPE_FIFO: - d_type = DT_FIFO; - break; - case SHFL_TYPE_DEV_CHAR: - d_type = DT_CHR; - break; - case SHFL_TYPE_DIRECTORY: - d_type = DT_DIR; - break; - case SHFL_TYPE_DEV_BLOCK: - d_type = DT_BLK; - break; - case SHFL_TYPE_FILE: - d_type = DT_REG; - break; - case SHFL_TYPE_SYMLINK: - d_type = DT_LNK; - break; - case SHFL_TYPE_SOCKET: - d_type = DT_SOCK; - break; - case SHFL_TYPE_WHITEOUT: - d_type = DT_WHT; - break; - default: - d_type = DT_UNKNOWN; - break; - } - return d_type; -} - -static bool vboxsf_dir_emit(struct file *dir, struct dir_context *ctx) -{ - struct vboxsf_sbi *sbi = VBOXSF_SBI(file_inode(dir)->i_sb); - struct vboxsf_dir_info *sf_d = dir->private_data; - struct shfl_dirinfo *info; - struct vboxsf_dir_buf *b; - unsigned int d_type; - loff_t i, cur = 0; - ino_t fake_ino; - size_t size; - int err; - - list_for_each_entry(b, &sf_d->info_list, head) { -try_next_entry: - if (ctx->pos >= cur + b->entries) { - cur += b->entries; - continue; - } - - /* - * Note the vboxsf_dir_info objects we are iterating over here - * are variable sized, so the info pointer may end up being - * unaligned. This is how we get the data from the host. - * Since vboxsf is only supported on x86 machines this is not - * a problem. - */ - for (i = 0, info = b->buf; i < ctx->pos - cur; i++) { - size = offsetof(struct shfl_dirinfo, name.string) + - info->name.size; - info = (struct shfl_dirinfo *)((uintptr_t)info + size); - } - - /* Info now points to the right entry, emit it. */ - d_type = vboxsf_get_d_type(info->info.attr.mode); - - /* - * On 32 bit systems pos is 64 signed, while ino is 32 bit - * unsigned so fake_ino may overflow, check for this. - */ - if ((ino_t)(ctx->pos + 1) != (u64)(ctx->pos + 1)) { - vbg_err("vboxsf: fake ino overflow, truncating dir\n"); - return false; - } - fake_ino = ctx->pos + 1; - - if (sbi->nls) { - char d_name[NAME_MAX]; - - err = vboxsf_nlscpy(sbi, d_name, NAME_MAX, - info->name.string.utf8, - info->name.length); - if (err) { - /* skip erroneous entry and proceed */ - ctx->pos += 1; - goto try_next_entry; - } - - return dir_emit(ctx, d_name, strlen(d_name), - fake_ino, d_type); - } - - return dir_emit(ctx, info->name.string.utf8, info->name.length, - fake_ino, d_type); - } - - return false; -} - -static int vboxsf_dir_iterate(struct file *dir, struct dir_context *ctx) -{ - bool keep_iterating; - - for (keep_iterating = true; keep_iterating; ctx->pos += 1) - keep_iterating = vboxsf_dir_emit(dir, ctx); - - return 0; -} - -const struct file_operations vboxsf_dir_fops = { - .open = vboxsf_dir_open, - .iterate = vboxsf_dir_iterate, - .release = vboxsf_dir_release, - .read = generic_read_dir, - .llseek = generic_file_llseek, -}; - -/* - * This is called during name resolution/lookup to check if the @dentry in - * the cache is still valid. the job is handled by vboxsf_inode_revalidate. - */ -static int vboxsf_dentry_revalidate(struct dentry *dentry, unsigned int flags) -{ - if (flags & LOOKUP_RCU) - return -ECHILD; - - if (d_really_is_positive(dentry)) - return vboxsf_inode_revalidate(dentry) == 0; - else - return vboxsf_stat_dentry(dentry, NULL) == -ENOENT; -} - -const struct dentry_operations vboxsf_dentry_ops = { - .d_revalidate = vboxsf_dentry_revalidate -}; - -/* iops */ - -static struct dentry *vboxsf_dir_lookup(struct inode *parent, - struct dentry *dentry, - unsigned int flags) -{ - struct vboxsf_sbi *sbi = VBOXSF_SBI(parent->i_sb); - struct shfl_fsobjinfo fsinfo; - struct inode *inode; - int err; - - dentry->d_time = jiffies; - - err = vboxsf_stat_dentry(dentry, &fsinfo); - if (err) { - inode = (err == -ENOENT) ? NULL : ERR_PTR(err); - } else { - inode = vboxsf_new_inode(parent->i_sb); - if (!IS_ERR(inode)) - vboxsf_init_inode(sbi, inode, &fsinfo); - } - - return d_splice_alias(inode, dentry); -} - -static int vboxsf_dir_instantiate(struct inode *parent, struct dentry *dentry, - struct shfl_fsobjinfo *info) -{ - struct vboxsf_sbi *sbi = VBOXSF_SBI(parent->i_sb); - struct vboxsf_inode *sf_i; - struct inode *inode; - - inode = vboxsf_new_inode(parent->i_sb); - if (IS_ERR(inode)) - return PTR_ERR(inode); - - sf_i = VBOXSF_I(inode); - /* The host may have given us different attr then requested */ - sf_i->force_restat = 1; - vboxsf_init_inode(sbi, inode, info); - - d_instantiate(dentry, inode); - - return 0; -} - -static int vboxsf_dir_create(struct inode *parent, struct dentry *dentry, - umode_t mode, int is_dir) -{ - struct vboxsf_inode *sf_parent_i = VBOXSF_I(parent); - struct vboxsf_sbi *sbi = VBOXSF_SBI(parent->i_sb); - struct shfl_createparms params = {}; - int err; - - params.handle = SHFL_HANDLE_NIL; - params.create_flags = SHFL_CF_ACT_CREATE_IF_NEW | - SHFL_CF_ACT_FAIL_IF_EXISTS | - SHFL_CF_ACCESS_READWRITE | - (is_dir ? SHFL_CF_DIRECTORY : 0); - params.info.attr.mode = (mode & 0777) | - (is_dir ? SHFL_TYPE_DIRECTORY : SHFL_TYPE_FILE); - params.info.attr.additional = SHFLFSOBJATTRADD_NOTHING; - - err = vboxsf_create_at_dentry(dentry, ¶ms); - if (err) - return err; - - if (params.result != SHFL_FILE_CREATED) - return -EPERM; - - vboxsf_close(sbi->root, params.handle); - - err = vboxsf_dir_instantiate(parent, dentry, ¶ms.info); - if (err) - return err; - - /* parent directory access/change time changed */ - sf_parent_i->force_restat = 1; - - return 0; -} - -static int vboxsf_dir_mkfile(struct inode *parent, struct dentry *dentry, - umode_t mode, bool excl) -{ - return vboxsf_dir_create(parent, dentry, mode, 0); -} - -static int vboxsf_dir_mkdir(struct inode *parent, struct dentry *dentry, - umode_t mode) -{ - return vboxsf_dir_create(parent, dentry, mode, 1); -} - -static int vboxsf_dir_unlink(struct inode *parent, struct dentry *dentry) -{ - struct vboxsf_sbi *sbi = VBOXSF_SBI(parent->i_sb); - struct vboxsf_inode *sf_parent_i = VBOXSF_I(parent); - struct inode *inode = d_inode(dentry); - struct shfl_string *path; - u32 flags; - int err; - - if (S_ISDIR(inode->i_mode)) - flags = SHFL_REMOVE_DIR; - else - flags = SHFL_REMOVE_FILE; - - if (S_ISLNK(inode->i_mode)) - flags |= SHFL_REMOVE_SYMLINK; - - path = vboxsf_path_from_dentry(sbi, dentry); - if (IS_ERR(path)) - return PTR_ERR(path); - - err = vboxsf_remove(sbi->root, path, flags); - __putname(path); - if (err) - return err; - - /* parent directory access/change time changed */ - sf_parent_i->force_restat = 1; - - return 0; -} - -static int vboxsf_dir_rename(struct inode *old_parent, - struct dentry *old_dentry, - struct inode *new_parent, - struct dentry *new_dentry, - unsigned int flags) -{ - struct vboxsf_sbi *sbi = VBOXSF_SBI(old_parent->i_sb); - struct vboxsf_inode *sf_old_parent_i = VBOXSF_I(old_parent); - struct vboxsf_inode *sf_new_parent_i = VBOXSF_I(new_parent); - u32 shfl_flags = SHFL_RENAME_FILE | SHFL_RENAME_REPLACE_IF_EXISTS; - struct shfl_string *old_path, *new_path; - int err; - - if (flags) - return -EINVAL; - - old_path = vboxsf_path_from_dentry(sbi, old_dentry); - if (IS_ERR(old_path)) - return PTR_ERR(old_path); - - new_path = vboxsf_path_from_dentry(sbi, new_dentry); - if (IS_ERR(new_path)) { - err = PTR_ERR(new_path); - goto err_put_old_path; - } - - if (d_inode(old_dentry)->i_mode & S_IFDIR) - shfl_flags = 0; - - err = vboxsf_rename(sbi->root, old_path, new_path, shfl_flags); - if (err == 0) { - /* parent directories access/change time changed */ - sf_new_parent_i->force_restat = 1; - sf_old_parent_i->force_restat = 1; - } - - __putname(new_path); -err_put_old_path: - __putname(old_path); - return err; -} - -static int vboxsf_dir_symlink(struct inode *parent, struct dentry *dentry, - const char *symname) -{ - struct vboxsf_inode *sf_parent_i = VBOXSF_I(parent); - struct vboxsf_sbi *sbi = VBOXSF_SBI(parent->i_sb); - int symname_size = strlen(symname) + 1; - struct shfl_string *path, *ssymname; - struct shfl_fsobjinfo info; - int err; - - path = vboxsf_path_from_dentry(sbi, dentry); - if (IS_ERR(path)) - return PTR_ERR(path); - - ssymname = kmalloc(SHFLSTRING_HEADER_SIZE + symname_size, GFP_KERNEL); - if (!ssymname) { - __putname(path); - return -ENOMEM; - } - ssymname->length = symname_size - 1; - ssymname->size = symname_size; - memcpy(ssymname->string.utf8, symname, symname_size); - - err = vboxsf_symlink(sbi->root, path, ssymname, &info); - kfree(ssymname); - __putname(path); - if (err) { - /* -EROFS means symlinks are note support -> -EPERM */ - return (err == -EROFS) ? -EPERM : err; - } - - err = vboxsf_dir_instantiate(parent, dentry, &info); - if (err) - return err; - - /* parent directory access/change time changed */ - sf_parent_i->force_restat = 1; - return 0; -} - -const struct inode_operations vboxsf_dir_iops = { - .lookup = vboxsf_dir_lookup, - .create = vboxsf_dir_mkfile, - .mkdir = vboxsf_dir_mkdir, - .rmdir = vboxsf_dir_unlink, - .unlink = vboxsf_dir_unlink, - .rename = vboxsf_dir_rename, - .symlink = vboxsf_dir_symlink, - .getattr = vboxsf_getattr, - .setattr = vboxsf_setattr, -}; diff --git a/drivers/staging/vboxsf/file.c b/drivers/staging/vboxsf/file.c deleted file mode 100644 index 4b61ccf83fca..000000000000 --- a/drivers/staging/vboxsf/file.c +++ /dev/null @@ -1,370 +0,0 @@ -// SPDX-License-Identifier: MIT -/* - * VirtualBox Guest Shared Folders support: Regular file inode and file ops. - * - * Copyright (C) 2006-2018 Oracle Corporation - */ - -#include -#include -#include -#include -#include -#include "vfsmod.h" - -struct vboxsf_handle { - u64 handle; - u32 root; - u32 access_flags; - struct kref refcount; - struct list_head head; -}; - -static int vboxsf_file_open(struct inode *inode, struct file *file) -{ - struct vboxsf_inode *sf_i = VBOXSF_I(inode); - struct shfl_createparms params = {}; - struct vboxsf_handle *sf_handle; - u32 access_flags = 0; - int err; - - sf_handle = kmalloc(sizeof(*sf_handle), GFP_KERNEL); - if (!sf_handle) - return -ENOMEM; - - /* - * We check the value of params.handle afterwards to find out if - * the call succeeded or failed, as the API does not seem to cleanly - * distinguish error and informational messages. - * - * Furthermore, we must set params.handle to SHFL_HANDLE_NIL to - * make the shared folders host service use our mode parameter. - */ - params.handle = SHFL_HANDLE_NIL; - if (file->f_flags & O_CREAT) { - params.create_flags |= SHFL_CF_ACT_CREATE_IF_NEW; - /* - * We ignore O_EXCL, as the Linux kernel seems to call create - * beforehand itself, so O_EXCL should always fail. - */ - if (file->f_flags & O_TRUNC) - params.create_flags |= SHFL_CF_ACT_OVERWRITE_IF_EXISTS; - else - params.create_flags |= SHFL_CF_ACT_OPEN_IF_EXISTS; - } else { - params.create_flags |= SHFL_CF_ACT_FAIL_IF_NEW; - if (file->f_flags & O_TRUNC) - params.create_flags |= SHFL_CF_ACT_OVERWRITE_IF_EXISTS; - } - - switch (file->f_flags & O_ACCMODE) { - case O_RDONLY: - access_flags |= SHFL_CF_ACCESS_READ; - break; - - case O_WRONLY: - access_flags |= SHFL_CF_ACCESS_WRITE; - break; - - case O_RDWR: - access_flags |= SHFL_CF_ACCESS_READWRITE; - break; - - default: - WARN_ON(1); - } - - if (file->f_flags & O_APPEND) - access_flags |= SHFL_CF_ACCESS_APPEND; - - params.create_flags |= access_flags; - params.info.attr.mode = inode->i_mode; - - err = vboxsf_create_at_dentry(file_dentry(file), ¶ms); - if (err == 0 && params.handle == SHFL_HANDLE_NIL) - err = (params.result == SHFL_FILE_EXISTS) ? -EEXIST : -ENOENT; - if (err) { - kfree(sf_handle); - return err; - } - - /* the host may have given us different attr then requested */ - sf_i->force_restat = 1; - - /* init our handle struct and add it to the inode's handles list */ - sf_handle->handle = params.handle; - sf_handle->root = VBOXSF_SBI(inode->i_sb)->root; - sf_handle->access_flags = access_flags; - kref_init(&sf_handle->refcount); - - mutex_lock(&sf_i->handle_list_mutex); - list_add(&sf_handle->head, &sf_i->handle_list); - mutex_unlock(&sf_i->handle_list_mutex); - - file->private_data = sf_handle; - return 0; -} - -static void vboxsf_handle_release(struct kref *refcount) -{ - struct vboxsf_handle *sf_handle = - container_of(refcount, struct vboxsf_handle, refcount); - - vboxsf_close(sf_handle->root, sf_handle->handle); - kfree(sf_handle); -} - -static int vboxsf_file_release(struct inode *inode, struct file *file) -{ - struct vboxsf_inode *sf_i = VBOXSF_I(inode); - struct vboxsf_handle *sf_handle = file->private_data; - - /* - * When a file is closed on our (the guest) side, we want any subsequent - * accesses done on the host side to see all changes done from our side. - */ - filemap_write_and_wait(inode->i_mapping); - - mutex_lock(&sf_i->handle_list_mutex); - list_del(&sf_handle->head); - mutex_unlock(&sf_i->handle_list_mutex); - - kref_put(&sf_handle->refcount, vboxsf_handle_release); - return 0; -} - -/* - * Write back dirty pages now, because there may not be any suitable - * open files later - */ -static void vboxsf_vma_close(struct vm_area_struct *vma) -{ - filemap_write_and_wait(vma->vm_file->f_mapping); -} - -static const struct vm_operations_struct vboxsf_file_vm_ops = { - .close = vboxsf_vma_close, - .fault = filemap_fault, - .map_pages = filemap_map_pages, -}; - -static int vboxsf_file_mmap(struct file *file, struct vm_area_struct *vma) -{ - int err; - - err = generic_file_mmap(file, vma); - if (!err) - vma->vm_ops = &vboxsf_file_vm_ops; - - return err; -} - -/* - * Note that since we are accessing files on the host's filesystem, files - * may always be changed underneath us by the host! - * - * The vboxsf API between the guest and the host does not offer any functions - * to deal with this. There is no inode-generation to check for changes, no - * events / callback on changes and no way to lock files. - * - * To avoid returning stale data when a file gets *opened* on our (the guest) - * side, we do a "stat" on the host side, then compare the mtime with the - * last known mtime and invalidate the page-cache if they differ. - * This is done from vboxsf_inode_revalidate(). - * - * When reads are done through the read_iter fop, it is possible to do - * further cache revalidation then, there are 3 options to deal with this: - * - * 1) Rely solely on the revalidation done at open time - * 2) Do another "stat" and compare mtime again. Unfortunately the vboxsf - * host API does not allow stat on handles, so we would need to use - * file->f_path.dentry and the stat will then fail if the file was unlinked - * or renamed (and there is no thing like NFS' silly-rename). So we get: - * 2a) "stat" and compare mtime, on stat failure invalidate the cache - * 2b) "stat" and compare mtime, on stat failure do nothing - * 3) Simply always call invalidate_inode_pages2_range on the range of the read - * - * Currently we are keeping things KISS and using option 1. this allows - * directly using generic_file_read_iter without wrapping it. - * - * This means that only data written on the host side before open() on - * the guest side is guaranteed to be seen by the guest. If necessary - * we may provide other read-cache strategies in the future and make this - * configurable through a mount option. - */ -const struct file_operations vboxsf_reg_fops = { - .llseek = generic_file_llseek, - .read_iter = generic_file_read_iter, - .write_iter = generic_file_write_iter, - .mmap = vboxsf_file_mmap, - .open = vboxsf_file_open, - .release = vboxsf_file_release, - .fsync = noop_fsync, - .splice_read = generic_file_splice_read, -}; - -const struct inode_operations vboxsf_reg_iops = { - .getattr = vboxsf_getattr, - .setattr = vboxsf_setattr -}; - -static int vboxsf_readpage(struct file *file, struct page *page) -{ - struct vboxsf_handle *sf_handle = file->private_data; - loff_t off = page_offset(page); - u32 nread = PAGE_SIZE; - u8 *buf; - int err; - - buf = kmap(page); - - err = vboxsf_read(sf_handle->root, sf_handle->handle, off, &nread, buf); - if (err == 0) { - memset(&buf[nread], 0, PAGE_SIZE - nread); - flush_dcache_page(page); - SetPageUptodate(page); - } else { - SetPageError(page); - } - - kunmap(page); - unlock_page(page); - return err; -} - -static struct vboxsf_handle *vboxsf_get_write_handle(struct vboxsf_inode *sf_i) -{ - struct vboxsf_handle *h, *sf_handle = NULL; - - mutex_lock(&sf_i->handle_list_mutex); - list_for_each_entry(h, &sf_i->handle_list, head) { - if (h->access_flags == SHFL_CF_ACCESS_WRITE || - h->access_flags == SHFL_CF_ACCESS_READWRITE) { - kref_get(&h->refcount); - sf_handle = h; - break; - } - } - mutex_unlock(&sf_i->handle_list_mutex); - - return sf_handle; -} - -static int vboxsf_writepage(struct page *page, struct writeback_control *wbc) -{ - struct inode *inode = page->mapping->host; - struct vboxsf_inode *sf_i = VBOXSF_I(inode); - struct vboxsf_handle *sf_handle; - loff_t off = page_offset(page); - loff_t size = i_size_read(inode); - u32 nwrite = PAGE_SIZE; - u8 *buf; - int err; - - if (off + PAGE_SIZE > size) - nwrite = size & ~PAGE_MASK; - - sf_handle = vboxsf_get_write_handle(sf_i); - if (!sf_handle) - return -EBADF; - - buf = kmap(page); - err = vboxsf_write(sf_handle->root, sf_handle->handle, - off, &nwrite, buf); - kunmap(page); - - kref_put(&sf_handle->refcount, vboxsf_handle_release); - - if (err == 0) { - ClearPageError(page); - /* mtime changed */ - sf_i->force_restat = 1; - } else { - ClearPageUptodate(page); - } - - unlock_page(page); - return err; -} - -static int vboxsf_write_end(struct file *file, struct address_space *mapping, - loff_t pos, unsigned int len, unsigned int copied, - struct page *page, void *fsdata) -{ - struct inode *inode = mapping->host; - struct vboxsf_handle *sf_handle = file->private_data; - unsigned int from = pos & ~PAGE_MASK; - u32 nwritten = len; - u8 *buf; - int err; - - buf = kmap(page); - err = vboxsf_write(sf_handle->root, sf_handle->handle, - pos, &nwritten, buf + from); - kunmap(page); - - if (err) { - nwritten = 0; - goto out; - } - - /* mtime changed */ - VBOXSF_I(inode)->force_restat = 1; - - if (!PageUptodate(page) && nwritten == PAGE_SIZE) - SetPageUptodate(page); - - pos += nwritten; - if (pos > inode->i_size) - i_size_write(inode, pos); - -out: - unlock_page(page); - put_page(page); - - return nwritten; -} - -const struct address_space_operations vboxsf_reg_aops = { - .readpage = vboxsf_readpage, - .writepage = vboxsf_writepage, - .set_page_dirty = __set_page_dirty_nobuffers, - .write_begin = simple_write_begin, - .write_end = vboxsf_write_end, -}; - -static const char *vboxsf_get_link(struct dentry *dentry, struct inode *inode, - struct delayed_call *done) -{ - struct vboxsf_sbi *sbi = VBOXSF_SBI(inode->i_sb); - struct shfl_string *path; - char *link; - int err; - - if (!dentry) - return ERR_PTR(-ECHILD); - - path = vboxsf_path_from_dentry(sbi, dentry); - if (IS_ERR(path)) - return (char *)path; - - link = kzalloc(PATH_MAX, GFP_KERNEL); - if (!link) { - __putname(path); - return ERR_PTR(-ENOMEM); - } - - err = vboxsf_readlink(sbi->root, path, PATH_MAX, link); - __putname(path); - if (err) { - kfree(link); - return ERR_PTR(err); - } - - set_delayed_call(done, kfree_link, link); - return link; -} - -const struct inode_operations vboxsf_lnk_iops = { - .get_link = vboxsf_get_link -}; diff --git a/drivers/staging/vboxsf/shfl_hostintf.h b/drivers/staging/vboxsf/shfl_hostintf.h deleted file mode 100644 index aca829062c12..000000000000 --- a/drivers/staging/vboxsf/shfl_hostintf.h +++ /dev/null @@ -1,901 +0,0 @@ -/* SPDX-License-Identifier: MIT */ -/* - * VirtualBox Shared Folders: host interface definition. - * - * Copyright (C) 2006-2018 Oracle Corporation - */ - -#ifndef SHFL_HOSTINTF_H -#define SHFL_HOSTINTF_H - -#include - -/* The max in/out buffer size for a FN_READ or FN_WRITE call */ -#define SHFL_MAX_RW_COUNT (16 * SZ_1M) - -/* - * Structures shared between guest and the service - * can be relocated and use offsets to point to variable - * length parts. - * - * Shared folders protocol works with handles. - * Before doing any action on a file system object, - * one have to obtain the object handle via a SHFL_FN_CREATE - * request. A handle must be closed with SHFL_FN_CLOSE. - */ - -enum { - SHFL_FN_QUERY_MAPPINGS = 1, /* Query mappings changes. */ - SHFL_FN_QUERY_MAP_NAME = 2, /* Query map name. */ - SHFL_FN_CREATE = 3, /* Open/create object. */ - SHFL_FN_CLOSE = 4, /* Close object handle. */ - SHFL_FN_READ = 5, /* Read object content. */ - SHFL_FN_WRITE = 6, /* Write new object content. */ - SHFL_FN_LOCK = 7, /* Lock/unlock a range in the object. */ - SHFL_FN_LIST = 8, /* List object content. */ - SHFL_FN_INFORMATION = 9, /* Query/set object information. */ - /* Note function number 10 is not used! */ - SHFL_FN_REMOVE = 11, /* Remove object */ - SHFL_FN_MAP_FOLDER_OLD = 12, /* Map folder (legacy) */ - SHFL_FN_UNMAP_FOLDER = 13, /* Unmap folder */ - SHFL_FN_RENAME = 14, /* Rename object */ - SHFL_FN_FLUSH = 15, /* Flush file */ - SHFL_FN_SET_UTF8 = 16, /* Select UTF8 filename encoding */ - SHFL_FN_MAP_FOLDER = 17, /* Map folder */ - SHFL_FN_READLINK = 18, /* Read symlink dest (as of VBox 4.0) */ - SHFL_FN_SYMLINK = 19, /* Create symlink (as of VBox 4.0) */ - SHFL_FN_SET_SYMLINKS = 20, /* Ask host to show symlinks (4.0+) */ -}; - -/* Root handles for a mapping are of type u32, Root handles are unique. */ -#define SHFL_ROOT_NIL UINT_MAX - -/* Shared folders handle for an opened object are of type u64. */ -#define SHFL_HANDLE_NIL ULLONG_MAX - -/* Hardcoded maximum length (in chars) of a shared folder name. */ -#define SHFL_MAX_LEN (256) -/* Hardcoded maximum number of shared folder mapping available to the guest. */ -#define SHFL_MAX_MAPPINGS (64) - -/** Shared folder string buffer structure. */ -struct shfl_string { - /** Allocated size of the string member in bytes. */ - u16 size; - - /** Length of string without trailing nul in bytes. */ - u16 length; - - /** UTF-8 or UTF-16 string. Nul terminated. */ - union { - u8 utf8[2]; - u16 utf16[1]; - u16 ucs2[1]; /* misnomer, use utf16. */ - } string; -}; -VMMDEV_ASSERT_SIZE(shfl_string, 6); - -/* The size of shfl_string w/o the string part. */ -#define SHFLSTRING_HEADER_SIZE 4 - -/* Calculate size of the string. */ -static inline u32 shfl_string_buf_size(const struct shfl_string *string) -{ - return string ? SHFLSTRING_HEADER_SIZE + string->size : 0; -} - -/* Set user id on execution (S_ISUID). */ -#define SHFL_UNIX_ISUID 0004000U -/* Set group id on execution (S_ISGID). */ -#define SHFL_UNIX_ISGID 0002000U -/* Sticky bit (S_ISVTX / S_ISTXT). */ -#define SHFL_UNIX_ISTXT 0001000U - -/* Owner readable (S_IRUSR). */ -#define SHFL_UNIX_IRUSR 0000400U -/* Owner writable (S_IWUSR). */ -#define SHFL_UNIX_IWUSR 0000200U -/* Owner executable (S_IXUSR). */ -#define SHFL_UNIX_IXUSR 0000100U - -/* Group readable (S_IRGRP). */ -#define SHFL_UNIX_IRGRP 0000040U -/* Group writable (S_IWGRP). */ -#define SHFL_UNIX_IWGRP 0000020U -/* Group executable (S_IXGRP). */ -#define SHFL_UNIX_IXGRP 0000010U - -/* Other readable (S_IROTH). */ -#define SHFL_UNIX_IROTH 0000004U -/* Other writable (S_IWOTH). */ -#define SHFL_UNIX_IWOTH 0000002U -/* Other executable (S_IXOTH). */ -#define SHFL_UNIX_IXOTH 0000001U - -/* Named pipe (fifo) (S_IFIFO). */ -#define SHFL_TYPE_FIFO 0010000U -/* Character device (S_IFCHR). */ -#define SHFL_TYPE_DEV_CHAR 0020000U -/* Directory (S_IFDIR). */ -#define SHFL_TYPE_DIRECTORY 0040000U -/* Block device (S_IFBLK). */ -#define SHFL_TYPE_DEV_BLOCK 0060000U -/* Regular file (S_IFREG). */ -#define SHFL_TYPE_FILE 0100000U -/* Symbolic link (S_IFLNK). */ -#define SHFL_TYPE_SYMLINK 0120000U -/* Socket (S_IFSOCK). */ -#define SHFL_TYPE_SOCKET 0140000U -/* Whiteout (S_IFWHT). */ -#define SHFL_TYPE_WHITEOUT 0160000U -/* Type mask (S_IFMT). */ -#define SHFL_TYPE_MASK 0170000U - -/* Checks the mode flags indicate a directory (S_ISDIR). */ -#define SHFL_IS_DIRECTORY(m) (((m) & SHFL_TYPE_MASK) == SHFL_TYPE_DIRECTORY) -/* Checks the mode flags indicate a symbolic link (S_ISLNK). */ -#define SHFL_IS_SYMLINK(m) (((m) & SHFL_TYPE_MASK) == SHFL_TYPE_SYMLINK) - -/** The available additional information in a shfl_fsobjattr object. */ -enum shfl_fsobjattr_add { - /** No additional information is available / requested. */ - SHFLFSOBJATTRADD_NOTHING = 1, - /** - * The additional unix attributes (shfl_fsobjattr::u::unix_attr) are - * available / requested. - */ - SHFLFSOBJATTRADD_UNIX, - /** - * The additional extended attribute size (shfl_fsobjattr::u::size) is - * available / requested. - */ - SHFLFSOBJATTRADD_EASIZE, - /** - * The last valid item (inclusive). - * The valid range is SHFLFSOBJATTRADD_NOTHING thru - * SHFLFSOBJATTRADD_LAST. - */ - SHFLFSOBJATTRADD_LAST = SHFLFSOBJATTRADD_EASIZE, - - /** The usual 32-bit hack. */ - SHFLFSOBJATTRADD_32BIT_SIZE_HACK = 0x7fffffff -}; - -/** - * Additional unix Attributes, these are available when - * shfl_fsobjattr.additional == SHFLFSOBJATTRADD_UNIX. - */ -struct shfl_fsobjattr_unix { - /** - * The user owning the filesystem object (st_uid). - * This field is ~0U if not supported. - */ - u32 uid; - - /** - * The group the filesystem object is assigned (st_gid). - * This field is ~0U if not supported. - */ - u32 gid; - - /** - * Number of hard links to this filesystem object (st_nlink). - * This field is 1 if the filesystem doesn't support hardlinking or - * the information isn't available. - */ - u32 hardlinks; - - /** - * The device number of the device which this filesystem object resides - * on (st_dev). This field is 0 if this information is not available. - */ - u32 inode_id_device; - - /** - * The unique identifier (within the filesystem) of this filesystem - * object (st_ino). Together with inode_id_device, this field can be - * used as a OS wide unique id, when both their values are not 0. - * This field is 0 if the information is not available. - */ - u64 inode_id; - - /** - * User flags (st_flags). - * This field is 0 if this information is not available. - */ - u32 flags; - - /** - * The current generation number (st_gen). - * This field is 0 if this information is not available. - */ - u32 generation_id; - - /** - * The device number of a char. or block device type object (st_rdev). - * This field is 0 if the file isn't a char. or block device or when - * the OS doesn't use the major+minor device idenfication scheme. - */ - u32 device; -} __packed; - -/** Extended attribute size. */ -struct shfl_fsobjattr_easize { - /** Size of EAs. */ - s64 cb; -} __packed; - -/** Shared folder filesystem object attributes. */ -struct shfl_fsobjattr { - /** Mode flags (st_mode). SHFL_UNIX_*, SHFL_TYPE_*, and SHFL_DOS_*. */ - u32 mode; - - /** The additional attributes available. */ - enum shfl_fsobjattr_add additional; - - /** - * Additional attributes. - * - * Unless explicitly specified to an API, the API can provide additional - * data as it is provided by the underlying OS. - */ - union { - struct shfl_fsobjattr_unix unix_attr; - struct shfl_fsobjattr_easize size; - } __packed u; -} __packed; -VMMDEV_ASSERT_SIZE(shfl_fsobjattr, 44); - -struct shfl_timespec { - s64 ns_relative_to_unix_epoch; -}; - -/** Filesystem object information structure. */ -struct shfl_fsobjinfo { - /** - * Logical size (st_size). - * For normal files this is the size of the file. - * For symbolic links, this is the length of the path name contained - * in the symbolic link. - * For other objects this fields needs to be specified. - */ - s64 size; - - /** Disk allocation size (st_blocks * DEV_BSIZE). */ - s64 allocated; - - /** Time of last access (st_atime). */ - struct shfl_timespec access_time; - - /** Time of last data modification (st_mtime). */ - struct shfl_timespec modification_time; - - /** - * Time of last status change (st_ctime). - * If not available this is set to modification_time. - */ - struct shfl_timespec change_time; - - /** - * Time of file birth (st_birthtime). - * If not available this is set to change_time. - */ - struct shfl_timespec birth_time; - - /** Attributes. */ - struct shfl_fsobjattr attr; - -} __packed; -VMMDEV_ASSERT_SIZE(shfl_fsobjinfo, 92); - -/** - * result of an open/create request. - * Along with handle value the result code - * identifies what has happened while - * trying to open the object. - */ -enum shfl_create_result { - SHFL_NO_RESULT, - /** Specified path does not exist. */ - SHFL_PATH_NOT_FOUND, - /** Path to file exists, but the last component does not. */ - SHFL_FILE_NOT_FOUND, - /** File already exists and either has been opened or not. */ - SHFL_FILE_EXISTS, - /** New file was created. */ - SHFL_FILE_CREATED, - /** Existing file was replaced or overwritten. */ - SHFL_FILE_REPLACED -}; - -/* No flags. Initialization value. */ -#define SHFL_CF_NONE (0x00000000) - -/* - * Only lookup the object, do not return a handle. When this is set all other - * flags are ignored. - */ -#define SHFL_CF_LOOKUP (0x00000001) - -/* - * Open parent directory of specified object. - * Useful for the corresponding Windows FSD flag - * and for opening paths like \\dir\\*.* to search the 'dir'. - */ -#define SHFL_CF_OPEN_TARGET_DIRECTORY (0x00000002) - -/* Create/open a directory. */ -#define SHFL_CF_DIRECTORY (0x00000004) - -/* - * Open/create action to do if object exists - * and if the object does not exists. - * REPLACE file means atomically DELETE and CREATE. - * OVERWRITE file means truncating the file to 0 and - * setting new size. - * When opening an existing directory REPLACE and OVERWRITE - * actions are considered invalid, and cause returning - * FILE_EXISTS with NIL handle. - */ -#define SHFL_CF_ACT_MASK_IF_EXISTS (0x000000f0) -#define SHFL_CF_ACT_MASK_IF_NEW (0x00000f00) - -/* What to do if object exists. */ -#define SHFL_CF_ACT_OPEN_IF_EXISTS (0x00000000) -#define SHFL_CF_ACT_FAIL_IF_EXISTS (0x00000010) -#define SHFL_CF_ACT_REPLACE_IF_EXISTS (0x00000020) -#define SHFL_CF_ACT_OVERWRITE_IF_EXISTS (0x00000030) - -/* What to do if object does not exist. */ -#define SHFL_CF_ACT_CREATE_IF_NEW (0x00000000) -#define SHFL_CF_ACT_FAIL_IF_NEW (0x00000100) - -/* Read/write requested access for the object. */ -#define SHFL_CF_ACCESS_MASK_RW (0x00003000) - -/* No access requested. */ -#define SHFL_CF_ACCESS_NONE (0x00000000) -/* Read access requested. */ -#define SHFL_CF_ACCESS_READ (0x00001000) -/* Write access requested. */ -#define SHFL_CF_ACCESS_WRITE (0x00002000) -/* Read/Write access requested. */ -#define SHFL_CF_ACCESS_READWRITE (0x00003000) - -/* Requested share access for the object. */ -#define SHFL_CF_ACCESS_MASK_DENY (0x0000c000) - -/* Allow any access. */ -#define SHFL_CF_ACCESS_DENYNONE (0x00000000) -/* Do not allow read. */ -#define SHFL_CF_ACCESS_DENYREAD (0x00004000) -/* Do not allow write. */ -#define SHFL_CF_ACCESS_DENYWRITE (0x00008000) -/* Do not allow access. */ -#define SHFL_CF_ACCESS_DENYALL (0x0000c000) - -/* Requested access to attributes of the object. */ -#define SHFL_CF_ACCESS_MASK_ATTR (0x00030000) - -/* No access requested. */ -#define SHFL_CF_ACCESS_ATTR_NONE (0x00000000) -/* Read access requested. */ -#define SHFL_CF_ACCESS_ATTR_READ (0x00010000) -/* Write access requested. */ -#define SHFL_CF_ACCESS_ATTR_WRITE (0x00020000) -/* Read/Write access requested. */ -#define SHFL_CF_ACCESS_ATTR_READWRITE (0x00030000) - -/* - * The file is opened in append mode. - * Ignored if SHFL_CF_ACCESS_WRITE is not set. - */ -#define SHFL_CF_ACCESS_APPEND (0x00040000) - -/** Create parameters buffer struct for SHFL_FN_CREATE call */ -struct shfl_createparms { - /** Returned handle of opened object. */ - u64 handle; - - /** Returned result of the operation */ - enum shfl_create_result result; - - /** SHFL_CF_* */ - u32 create_flags; - - /** - * Attributes of object to create and - * returned actual attributes of opened/created object. - */ - struct shfl_fsobjinfo info; -} __packed; - -/** Shared Folder directory information */ -struct shfl_dirinfo { - /** Full information about the object. */ - struct shfl_fsobjinfo info; - /** - * The length of the short field (number of UTF16 chars). - * It is 16-bit for reasons of alignment. - */ - u16 short_name_len; - /** - * The short name for 8.3 compatibility. - * Empty string if not available. - */ - u16 short_name[14]; - struct shfl_string name; -}; - -/** Shared folder filesystem properties. */ -struct shfl_fsproperties { - /** - * The maximum size of a filesystem object name. - * This does not include the '\\0'. - */ - u32 max_component_len; - - /** - * True if the filesystem is remote. - * False if the filesystem is local. - */ - bool remote; - - /** - * True if the filesystem is case sensitive. - * False if the filesystem is case insensitive. - */ - bool case_sensitive; - - /** - * True if the filesystem is mounted read only. - * False if the filesystem is mounted read write. - */ - bool read_only; - - /** - * True if the filesystem can encode unicode object names. - * False if it can't. - */ - bool supports_unicode; - - /** - * True if the filesystem is compresses. - * False if it isn't or we don't know. - */ - bool compressed; - - /** - * True if the filesystem compresses of individual files. - * False if it doesn't or we don't know. - */ - bool file_compression; -}; -VMMDEV_ASSERT_SIZE(shfl_fsproperties, 12); - -struct shfl_volinfo { - s64 total_allocation_bytes; - s64 available_allocation_bytes; - u32 bytes_per_allocation_unit; - u32 bytes_per_sector; - u32 serial; - struct shfl_fsproperties properties; -}; - - -/** SHFL_FN_MAP_FOLDER Parameters structure. */ -struct shfl_map_folder { - /** - * pointer, in: - * Points to struct shfl_string buffer. - */ - struct vmmdev_hgcm_function_parameter path; - - /** - * pointer, out: SHFLROOT (u32) - * Root handle of the mapping which name is queried. - */ - struct vmmdev_hgcm_function_parameter root; - - /** - * pointer, in: UTF16 - * Path delimiter - */ - struct vmmdev_hgcm_function_parameter delimiter; - - /** - * pointer, in: SHFLROOT (u32) - * Case senstive flag - */ - struct vmmdev_hgcm_function_parameter case_sensitive; - -}; - -/* Number of parameters */ -#define SHFL_CPARMS_MAP_FOLDER (4) - - -/** SHFL_FN_UNMAP_FOLDER Parameters structure. */ -struct shfl_unmap_folder { - /** - * pointer, in: SHFLROOT (u32) - * Root handle of the mapping which name is queried. - */ - struct vmmdev_hgcm_function_parameter root; - -}; - -/* Number of parameters */ -#define SHFL_CPARMS_UNMAP_FOLDER (1) - - -/** SHFL_FN_CREATE Parameters structure. */ -struct shfl_create { - /** - * pointer, in: SHFLROOT (u32) - * Root handle of the mapping which name is queried. - */ - struct vmmdev_hgcm_function_parameter root; - - /** - * pointer, in: - * Points to struct shfl_string buffer. - */ - struct vmmdev_hgcm_function_parameter path; - - /** - * pointer, in/out: - * Points to struct shfl_createparms buffer. - */ - struct vmmdev_hgcm_function_parameter parms; - -}; - -/* Number of parameters */ -#define SHFL_CPARMS_CREATE (3) - - -/** SHFL_FN_CLOSE Parameters structure. */ -struct shfl_close { - /** - * pointer, in: SHFLROOT (u32) - * Root handle of the mapping which name is queried. - */ - struct vmmdev_hgcm_function_parameter root; - - /** - * value64, in: - * SHFLHANDLE (u64) of object to close. - */ - struct vmmdev_hgcm_function_parameter handle; - -}; - -/* Number of parameters */ -#define SHFL_CPARMS_CLOSE (2) - - -/** SHFL_FN_READ Parameters structure. */ -struct shfl_read { - /** - * pointer, in: SHFLROOT (u32) - * Root handle of the mapping which name is queried. - */ - struct vmmdev_hgcm_function_parameter root; - - /** - * value64, in: - * SHFLHANDLE (u64) of object to read from. - */ - struct vmmdev_hgcm_function_parameter handle; - - /** - * value64, in: - * Offset to read from. - */ - struct vmmdev_hgcm_function_parameter offset; - - /** - * value64, in/out: - * Bytes to read/How many were read. - */ - struct vmmdev_hgcm_function_parameter cb; - - /** - * pointer, out: - * Buffer to place data to. - */ - struct vmmdev_hgcm_function_parameter buffer; - -}; - -/* Number of parameters */ -#define SHFL_CPARMS_READ (5) - - -/** SHFL_FN_WRITE Parameters structure. */ -struct shfl_write { - /** - * pointer, in: SHFLROOT (u32) - * Root handle of the mapping which name is queried. - */ - struct vmmdev_hgcm_function_parameter root; - - /** - * value64, in: - * SHFLHANDLE (u64) of object to write to. - */ - struct vmmdev_hgcm_function_parameter handle; - - /** - * value64, in: - * Offset to write to. - */ - struct vmmdev_hgcm_function_parameter offset; - - /** - * value64, in/out: - * Bytes to write/How many were written. - */ - struct vmmdev_hgcm_function_parameter cb; - - /** - * pointer, in: - * Data to write. - */ - struct vmmdev_hgcm_function_parameter buffer; - -}; - -/* Number of parameters */ -#define SHFL_CPARMS_WRITE (5) - - -/* - * SHFL_FN_LIST - * Listing information includes variable length RTDIRENTRY[EX] structures. - */ - -#define SHFL_LIST_NONE 0 -#define SHFL_LIST_RETURN_ONE 1 - -/** SHFL_FN_LIST Parameters structure. */ -struct shfl_list { - /** - * pointer, in: SHFLROOT (u32) - * Root handle of the mapping which name is queried. - */ - struct vmmdev_hgcm_function_parameter root; - - /** - * value64, in: - * SHFLHANDLE (u64) of object to be listed. - */ - struct vmmdev_hgcm_function_parameter handle; - - /** - * value32, in: - * List flags SHFL_LIST_*. - */ - struct vmmdev_hgcm_function_parameter flags; - - /** - * value32, in/out: - * Bytes to be used for listing information/How many bytes were used. - */ - struct vmmdev_hgcm_function_parameter cb; - - /** - * pointer, in/optional - * Points to struct shfl_string buffer that specifies a search path. - */ - struct vmmdev_hgcm_function_parameter path; - - /** - * pointer, out: - * Buffer to place listing information to. (struct shfl_dirinfo) - */ - struct vmmdev_hgcm_function_parameter buffer; - - /** - * value32, in/out: - * Indicates a key where the listing must be resumed. - * in: 0 means start from begin of object. - * out: 0 means listing completed. - */ - struct vmmdev_hgcm_function_parameter resume_point; - - /** - * pointer, out: - * Number of files returned - */ - struct vmmdev_hgcm_function_parameter file_count; -}; - -/* Number of parameters */ -#define SHFL_CPARMS_LIST (8) - - -/** SHFL_FN_READLINK Parameters structure. */ -struct shfl_readLink { - /** - * pointer, in: SHFLROOT (u32) - * Root handle of the mapping which name is queried. - */ - struct vmmdev_hgcm_function_parameter root; - - /** - * pointer, in: - * Points to struct shfl_string buffer. - */ - struct vmmdev_hgcm_function_parameter path; - - /** - * pointer, out: - * Buffer to place data to. - */ - struct vmmdev_hgcm_function_parameter buffer; - -}; - -/* Number of parameters */ -#define SHFL_CPARMS_READLINK (3) - - -/* SHFL_FN_INFORMATION */ - -/* Mask of Set/Get bit. */ -#define SHFL_INFO_MODE_MASK (0x1) -/* Get information */ -#define SHFL_INFO_GET (0x0) -/* Set information */ -#define SHFL_INFO_SET (0x1) - -/* Get name of the object. */ -#define SHFL_INFO_NAME (0x2) -/* Set size of object (extend/trucate); only applies to file objects */ -#define SHFL_INFO_SIZE (0x4) -/* Get/Set file object info. */ -#define SHFL_INFO_FILE (0x8) -/* Get volume information. */ -#define SHFL_INFO_VOLUME (0x10) - -/** SHFL_FN_INFORMATION Parameters structure. */ -struct shfl_information { - /** - * pointer, in: SHFLROOT (u32) - * Root handle of the mapping which name is queried. - */ - struct vmmdev_hgcm_function_parameter root; - - /** - * value64, in: - * SHFLHANDLE (u64) of object to be listed. - */ - struct vmmdev_hgcm_function_parameter handle; - - /** - * value32, in: - * SHFL_INFO_* - */ - struct vmmdev_hgcm_function_parameter flags; - - /** - * value32, in/out: - * Bytes to be used for information/How many bytes were used. - */ - struct vmmdev_hgcm_function_parameter cb; - - /** - * pointer, in/out: - * Information to be set/get (shfl_fsobjinfo or shfl_string). Do not - * forget to set the shfl_fsobjinfo::attr::additional for a get - * operation as well. - */ - struct vmmdev_hgcm_function_parameter info; - -}; - -/* Number of parameters */ -#define SHFL_CPARMS_INFORMATION (5) - - -/* SHFL_FN_REMOVE */ - -#define SHFL_REMOVE_FILE (0x1) -#define SHFL_REMOVE_DIR (0x2) -#define SHFL_REMOVE_SYMLINK (0x4) - -/** SHFL_FN_REMOVE Parameters structure. */ -struct shfl_remove { - /** - * pointer, in: SHFLROOT (u32) - * Root handle of the mapping which name is queried. - */ - struct vmmdev_hgcm_function_parameter root; - - /** - * pointer, in: - * Points to struct shfl_string buffer. - */ - struct vmmdev_hgcm_function_parameter path; - - /** - * value32, in: - * remove flags (file/directory) - */ - struct vmmdev_hgcm_function_parameter flags; - -}; - -#define SHFL_CPARMS_REMOVE (3) - - -/* SHFL_FN_RENAME */ - -#define SHFL_RENAME_FILE (0x1) -#define SHFL_RENAME_DIR (0x2) -#define SHFL_RENAME_REPLACE_IF_EXISTS (0x4) - -/** SHFL_FN_RENAME Parameters structure. */ -struct shfl_rename { - /** - * pointer, in: SHFLROOT (u32) - * Root handle of the mapping which name is queried. - */ - struct vmmdev_hgcm_function_parameter root; - - /** - * pointer, in: - * Points to struct shfl_string src. - */ - struct vmmdev_hgcm_function_parameter src; - - /** - * pointer, in: - * Points to struct shfl_string dest. - */ - struct vmmdev_hgcm_function_parameter dest; - - /** - * value32, in: - * rename flags (file/directory) - */ - struct vmmdev_hgcm_function_parameter flags; - -}; - -#define SHFL_CPARMS_RENAME (4) - - -/** SHFL_FN_SYMLINK Parameters structure. */ -struct shfl_symlink { - /** - * pointer, in: SHFLROOT (u32) - * Root handle of the mapping which name is queried. - */ - struct vmmdev_hgcm_function_parameter root; - - /** - * pointer, in: - * Points to struct shfl_string of path for the new symlink. - */ - struct vmmdev_hgcm_function_parameter new_path; - - /** - * pointer, in: - * Points to struct shfl_string of destination for symlink. - */ - struct vmmdev_hgcm_function_parameter old_path; - - /** - * pointer, out: - * Information about created symlink. - */ - struct vmmdev_hgcm_function_parameter info; - -}; - -#define SHFL_CPARMS_SYMLINK (4) - -#endif diff --git a/drivers/staging/vboxsf/super.c b/drivers/staging/vboxsf/super.c deleted file mode 100644 index 0bf4d724aefd..000000000000 --- a/drivers/staging/vboxsf/super.c +++ /dev/null @@ -1,501 +0,0 @@ -// SPDX-License-Identifier: MIT -/* - * VirtualBox Guest Shared Folders support: Virtual File System. - * - * Module initialization/finalization - * File system registration/deregistration - * Superblock reading - * Few utility functions - * - * Copyright (C) 2006-2018 Oracle Corporation - */ - -#include -#include -#include -#include -#include -#include -#include -#include "vfsmod.h" - -#define VBOXSF_SUPER_MAGIC 0x786f4256 /* 'VBox' little endian */ - -#define VBSF_MOUNT_SIGNATURE_BYTE_0 ('\000') -#define VBSF_MOUNT_SIGNATURE_BYTE_1 ('\377') -#define VBSF_MOUNT_SIGNATURE_BYTE_2 ('\376') -#define VBSF_MOUNT_SIGNATURE_BYTE_3 ('\375') - -static int follow_symlinks; -module_param(follow_symlinks, int, 0444); -MODULE_PARM_DESC(follow_symlinks, - "Let host resolve symlinks rather than showing them"); - -static DEFINE_IDA(vboxsf_bdi_ida); -static DEFINE_MUTEX(vboxsf_setup_mutex); -static bool vboxsf_setup_done; -static struct super_operations vboxsf_super_ops; /* forward declaration */ -static struct kmem_cache *vboxsf_inode_cachep; - -static char * const vboxsf_default_nls = CONFIG_NLS_DEFAULT; - -enum { opt_nls, opt_uid, opt_gid, opt_ttl, opt_dmode, opt_fmode, - opt_dmask, opt_fmask }; - -static const struct fs_parameter_spec vboxsf_param_specs[] = { - fsparam_string ("nls", opt_nls), - fsparam_u32 ("uid", opt_uid), - fsparam_u32 ("gid", opt_gid), - fsparam_u32 ("ttl", opt_ttl), - fsparam_u32oct ("dmode", opt_dmode), - fsparam_u32oct ("fmode", opt_fmode), - fsparam_u32oct ("dmask", opt_dmask), - fsparam_u32oct ("fmask", opt_fmask), - {} -}; - -static const struct fs_parameter_description vboxsf_fs_parameters = { - .name = "vboxsf", - .specs = vboxsf_param_specs, -}; - -static int vboxsf_parse_param(struct fs_context *fc, struct fs_parameter *param) -{ - struct vboxsf_fs_context *ctx = fc->fs_private; - struct fs_parse_result result; - kuid_t uid; - kgid_t gid; - int opt; - - opt = fs_parse(fc, &vboxsf_fs_parameters, param, &result); - if (opt < 0) - return opt; - - switch (opt) { - case opt_nls: - if (fc->purpose != FS_CONTEXT_FOR_MOUNT) { - vbg_err("vboxsf: Cannot reconfigure nls option\n"); - return -EINVAL; - } - ctx->nls_name = param->string; - param->string = NULL; - break; - case opt_uid: - uid = make_kuid(current_user_ns(), result.uint_32); - if (!uid_valid(uid)) - return -EINVAL; - ctx->o.uid = uid; - break; - case opt_gid: - gid = make_kgid(current_user_ns(), result.uint_32); - if (!gid_valid(gid)) - return -EINVAL; - ctx->o.gid = gid; - break; - case opt_ttl: - ctx->o.ttl = msecs_to_jiffies(result.uint_32); - break; - case opt_dmode: - if (result.uint_32 & ~0777) - return -EINVAL; - ctx->o.dmode = result.uint_32; - ctx->o.dmode_set = true; - break; - case opt_fmode: - if (result.uint_32 & ~0777) - return -EINVAL; - ctx->o.fmode = result.uint_32; - ctx->o.fmode_set = true; - break; - case opt_dmask: - if (result.uint_32 & ~07777) - return -EINVAL; - ctx->o.dmask = result.uint_32; - break; - case opt_fmask: - if (result.uint_32 & ~07777) - return -EINVAL; - ctx->o.fmask = result.uint_32; - break; - default: - return -EINVAL; - } - - return 0; -} - -static int vboxsf_fill_super(struct super_block *sb, struct fs_context *fc) -{ - struct vboxsf_fs_context *ctx = fc->fs_private; - struct shfl_string *folder_name, root_path; - struct vboxsf_sbi *sbi; - struct dentry *droot; - struct inode *iroot; - char *nls_name; - size_t size; - int err; - - if (!fc->source) - return -EINVAL; - - sbi = kzalloc(sizeof(*sbi), GFP_KERNEL); - if (!sbi) - return -ENOMEM; - - sbi->o = ctx->o; - idr_init(&sbi->ino_idr); - spin_lock_init(&sbi->ino_idr_lock); - sbi->next_generation = 1; - sbi->bdi_id = -1; - - /* Load nls if not utf8 */ - nls_name = ctx->nls_name ? ctx->nls_name : vboxsf_default_nls; - if (strcmp(nls_name, "utf8") != 0) { - if (nls_name == vboxsf_default_nls) - sbi->nls = load_nls_default(); - else - sbi->nls = load_nls(nls_name); - - if (!sbi->nls) { - vbg_err("vboxsf: Count not load '%s' nls\n", nls_name); - err = -EINVAL; - goto fail_free; - } - } - - sbi->bdi_id = ida_simple_get(&vboxsf_bdi_ida, 0, 0, GFP_KERNEL); - if (sbi->bdi_id < 0) { - err = sbi->bdi_id; - goto fail_free; - } - - err = super_setup_bdi_name(sb, "vboxsf-%s.%d", fc->source, sbi->bdi_id); - if (err) - goto fail_free; - - /* Turn source into a shfl_string and map the folder */ - size = strlen(fc->source) + 1; - folder_name = kmalloc(SHFLSTRING_HEADER_SIZE + size, GFP_KERNEL); - if (!folder_name) { - err = -ENOMEM; - goto fail_free; - } - folder_name->size = size; - folder_name->length = size - 1; - strlcpy(folder_name->string.utf8, fc->source, size); - err = vboxsf_map_folder(folder_name, &sbi->root); - kfree(folder_name); - if (err) { - vbg_err("vboxsf: Host rejected mount of '%s' with error %d\n", - fc->source, err); - goto fail_free; - } - - root_path.length = 1; - root_path.size = 2; - root_path.string.utf8[0] = '/'; - root_path.string.utf8[1] = 0; - err = vboxsf_stat(sbi, &root_path, &sbi->root_info); - if (err) - goto fail_unmap; - - sb->s_magic = VBOXSF_SUPER_MAGIC; - sb->s_blocksize = 1024; - sb->s_maxbytes = MAX_LFS_FILESIZE; - sb->s_op = &vboxsf_super_ops; - sb->s_d_op = &vboxsf_dentry_ops; - - iroot = iget_locked(sb, 0); - if (!iroot) { - err = -ENOMEM; - goto fail_unmap; - } - vboxsf_init_inode(sbi, iroot, &sbi->root_info); - unlock_new_inode(iroot); - - droot = d_make_root(iroot); - if (!droot) { - err = -ENOMEM; - goto fail_unmap; - } - - sb->s_root = droot; - sb->s_fs_info = sbi; - return 0; - -fail_unmap: - vboxsf_unmap_folder(sbi->root); -fail_free: - if (sbi->bdi_id >= 0) - ida_simple_remove(&vboxsf_bdi_ida, sbi->bdi_id); - if (sbi->nls) - unload_nls(sbi->nls); - idr_destroy(&sbi->ino_idr); - kfree(sbi); - return err; -} - -static void vboxsf_inode_init_once(void *data) -{ - struct vboxsf_inode *sf_i = data; - - mutex_init(&sf_i->handle_list_mutex); - inode_init_once(&sf_i->vfs_inode); -} - -static struct inode *vboxsf_alloc_inode(struct super_block *sb) -{ - struct vboxsf_inode *sf_i; - - sf_i = kmem_cache_alloc(vboxsf_inode_cachep, GFP_NOFS); - if (!sf_i) - return NULL; - - sf_i->force_restat = 0; - INIT_LIST_HEAD(&sf_i->handle_list); - - return &sf_i->vfs_inode; -} - -static void vboxsf_free_inode(struct inode *inode) -{ - struct vboxsf_sbi *sbi = VBOXSF_SBI(inode->i_sb); - unsigned long flags; - - spin_lock_irqsave(&sbi->ino_idr_lock, flags); - idr_remove(&sbi->ino_idr, inode->i_ino); - spin_unlock_irqrestore(&sbi->ino_idr_lock, flags); - kmem_cache_free(vboxsf_inode_cachep, VBOXSF_I(inode)); -} - -static void vboxsf_put_super(struct super_block *sb) -{ - struct vboxsf_sbi *sbi = VBOXSF_SBI(sb); - - vboxsf_unmap_folder(sbi->root); - if (sbi->bdi_id >= 0) - ida_simple_remove(&vboxsf_bdi_ida, sbi->bdi_id); - if (sbi->nls) - unload_nls(sbi->nls); - - /* - * vboxsf_free_inode uses the idr, make sure all delayed rcu free - * inodes are flushed. - */ - rcu_barrier(); - idr_destroy(&sbi->ino_idr); - kfree(sbi); -} - -static int vboxsf_statfs(struct dentry *dentry, struct kstatfs *stat) -{ - struct super_block *sb = dentry->d_sb; - struct shfl_volinfo shfl_volinfo; - struct vboxsf_sbi *sbi; - u32 buf_len; - int err; - - sbi = VBOXSF_SBI(sb); - buf_len = sizeof(shfl_volinfo); - err = vboxsf_fsinfo(sbi->root, 0, SHFL_INFO_GET | SHFL_INFO_VOLUME, - &buf_len, &shfl_volinfo); - if (err) - return err; - - stat->f_type = VBOXSF_SUPER_MAGIC; - stat->f_bsize = shfl_volinfo.bytes_per_allocation_unit; - - do_div(shfl_volinfo.total_allocation_bytes, - shfl_volinfo.bytes_per_allocation_unit); - stat->f_blocks = shfl_volinfo.total_allocation_bytes; - - do_div(shfl_volinfo.available_allocation_bytes, - shfl_volinfo.bytes_per_allocation_unit); - stat->f_bfree = shfl_volinfo.available_allocation_bytes; - stat->f_bavail = shfl_volinfo.available_allocation_bytes; - - stat->f_files = 1000; - /* - * Don't return 0 here since the guest may then think that it is not - * possible to create any more files. - */ - stat->f_ffree = 1000000; - stat->f_fsid.val[0] = 0; - stat->f_fsid.val[1] = 0; - stat->f_namelen = 255; - return 0; -} - -static struct super_operations vboxsf_super_ops = { - .alloc_inode = vboxsf_alloc_inode, - .free_inode = vboxsf_free_inode, - .put_super = vboxsf_put_super, - .statfs = vboxsf_statfs, -}; - -static int vboxsf_setup(void) -{ - int err; - - mutex_lock(&vboxsf_setup_mutex); - - if (vboxsf_setup_done) - goto success; - - vboxsf_inode_cachep = - kmem_cache_create("vboxsf_inode_cache", - sizeof(struct vboxsf_inode), 0, - (SLAB_RECLAIM_ACCOUNT | SLAB_MEM_SPREAD | - SLAB_ACCOUNT), - vboxsf_inode_init_once); - if (!vboxsf_inode_cachep) { - err = -ENOMEM; - goto fail_nomem; - } - - err = vboxsf_connect(); - if (err) { - vbg_err("vboxsf: err %d connecting to guest PCI-device\n", err); - vbg_err("vboxsf: make sure you are inside a VirtualBox VM\n"); - vbg_err("vboxsf: and check dmesg for vboxguest errors\n"); - goto fail_free_cache; - } - - err = vboxsf_set_utf8(); - if (err) { - vbg_err("vboxsf_setutf8 error %d\n", err); - goto fail_disconnect; - } - - if (!follow_symlinks) { - err = vboxsf_set_symlinks(); - if (err) - vbg_warn("vboxsf: Unable to show symlinks: %d\n", err); - } - - vboxsf_setup_done = true; -success: - mutex_unlock(&vboxsf_setup_mutex); - return 0; - -fail_disconnect: - vboxsf_disconnect(); -fail_free_cache: - kmem_cache_destroy(vboxsf_inode_cachep); -fail_nomem: - mutex_unlock(&vboxsf_setup_mutex); - return err; -} - -static int vboxsf_parse_monolithic(struct fs_context *fc, void *data) -{ - char *options = data; - - if (options && options[0] == VBSF_MOUNT_SIGNATURE_BYTE_0 && - options[1] == VBSF_MOUNT_SIGNATURE_BYTE_1 && - options[2] == VBSF_MOUNT_SIGNATURE_BYTE_2 && - options[3] == VBSF_MOUNT_SIGNATURE_BYTE_3) { - vbg_err("vboxsf: Old binary mount data not supported, remove obsolete mount.vboxsf and/or update your VBoxService.\n"); - return -EINVAL; - } - - return generic_parse_monolithic(fc, data); -} - -static int vboxsf_get_tree(struct fs_context *fc) -{ - int err; - - err = vboxsf_setup(); - if (err) - return err; - - return vfs_get_super(fc, vfs_get_independent_super, vboxsf_fill_super); -} - -static int vboxsf_reconfigure(struct fs_context *fc) -{ - struct vboxsf_sbi *sbi = VBOXSF_SBI(fc->root->d_sb); - struct vboxsf_fs_context *ctx = fc->fs_private; - struct inode *iroot; - - iroot = ilookup(fc->root->d_sb, 0); - if (!iroot) - return -ENOENT; - - /* Apply changed options to the root inode */ - sbi->o = ctx->o; - vboxsf_init_inode(sbi, iroot, &sbi->root_info); - - return 0; -} - -static void vboxsf_free_fc(struct fs_context *fc) -{ - struct vboxsf_fs_context *ctx = fc->fs_private; - - kfree(ctx->nls_name); - kfree(ctx); -} - -static const struct fs_context_operations vboxsf_context_ops = { - .free = vboxsf_free_fc, - .parse_param = vboxsf_parse_param, - .parse_monolithic = vboxsf_parse_monolithic, - .get_tree = vboxsf_get_tree, - .reconfigure = vboxsf_reconfigure, -}; - -static int vboxsf_init_fs_context(struct fs_context *fc) -{ - struct vboxsf_fs_context *ctx; - - ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); - if (!ctx) - return -ENOMEM; - - current_uid_gid(&ctx->o.uid, &ctx->o.gid); - - fc->fs_private = ctx; - fc->ops = &vboxsf_context_ops; - return 0; -} - -static struct file_system_type vboxsf_fs_type = { - .owner = THIS_MODULE, - .name = "vboxsf", - .init_fs_context = vboxsf_init_fs_context, - .parameters = &vboxsf_fs_parameters, - .kill_sb = kill_anon_super -}; - -/* Module initialization/finalization handlers */ -static int __init vboxsf_init(void) -{ - return register_filesystem(&vboxsf_fs_type); -} - -static void __exit vboxsf_fini(void) -{ - unregister_filesystem(&vboxsf_fs_type); - - mutex_lock(&vboxsf_setup_mutex); - if (vboxsf_setup_done) { - vboxsf_disconnect(); - /* - * Make sure all delayed rcu free inodes are flushed - * before we destroy the cache. - */ - rcu_barrier(); - kmem_cache_destroy(vboxsf_inode_cachep); - } - mutex_unlock(&vboxsf_setup_mutex); -} - -module_init(vboxsf_init); -module_exit(vboxsf_fini); - -MODULE_DESCRIPTION("Oracle VM VirtualBox Module for Host File System Access"); -MODULE_AUTHOR("Oracle Corporation"); -MODULE_LICENSE("GPL v2"); -MODULE_ALIAS_FS("vboxsf"); diff --git a/drivers/staging/vboxsf/utils.c b/drivers/staging/vboxsf/utils.c deleted file mode 100644 index 34a49e6f74fc..000000000000 --- a/drivers/staging/vboxsf/utils.c +++ /dev/null @@ -1,551 +0,0 @@ -// SPDX-License-Identifier: MIT -/* - * VirtualBox Guest Shared Folders support: Utility functions. - * Mainly conversion from/to VirtualBox/Linux data structures. - * - * Copyright (C) 2006-2018 Oracle Corporation - */ - -#include -#include -#include -#include -#include "vfsmod.h" - -struct inode *vboxsf_new_inode(struct super_block *sb) -{ - struct vboxsf_sbi *sbi = VBOXSF_SBI(sb); - struct inode *inode; - unsigned long flags; - int cursor, ret; - u32 gen; - - inode = new_inode(sb); - if (!inode) - return ERR_PTR(-ENOMEM); - - idr_preload(GFP_KERNEL); - spin_lock_irqsave(&sbi->ino_idr_lock, flags); - cursor = idr_get_cursor(&sbi->ino_idr); - ret = idr_alloc_cyclic(&sbi->ino_idr, inode, 1, 0, GFP_ATOMIC); - if (ret >= 0 && ret < cursor) - sbi->next_generation++; - gen = sbi->next_generation; - spin_unlock_irqrestore(&sbi->ino_idr_lock, flags); - idr_preload_end(); - - if (ret < 0) { - iput(inode); - return ERR_PTR(ret); - } - - inode->i_ino = ret; - inode->i_generation = gen; - return inode; -} - -/* set [inode] attributes based on [info], uid/gid based on [sbi] */ -void vboxsf_init_inode(struct vboxsf_sbi *sbi, struct inode *inode, - const struct shfl_fsobjinfo *info) -{ - const struct shfl_fsobjattr *attr; - s64 allocated; - int mode; - - attr = &info->attr; - -#define mode_set(r) ((attr->mode & (SHFL_UNIX_##r)) ? (S_##r) : 0) - - mode = mode_set(IRUSR); - mode |= mode_set(IWUSR); - mode |= mode_set(IXUSR); - - mode |= mode_set(IRGRP); - mode |= mode_set(IWGRP); - mode |= mode_set(IXGRP); - - mode |= mode_set(IROTH); - mode |= mode_set(IWOTH); - mode |= mode_set(IXOTH); - -#undef mode_set - - /* We use the host-side values for these */ - inode->i_flags |= S_NOATIME | S_NOCMTIME; - inode->i_mapping->a_ops = &vboxsf_reg_aops; - - if (SHFL_IS_DIRECTORY(attr->mode)) { - inode->i_mode = sbi->o.dmode_set ? sbi->o.dmode : mode; - inode->i_mode &= ~sbi->o.dmask; - inode->i_mode |= S_IFDIR; - inode->i_op = &vboxsf_dir_iops; - inode->i_fop = &vboxsf_dir_fops; - /* - * XXX: this probably should be set to the number of entries - * in the directory plus two (. ..) - */ - set_nlink(inode, 1); - } else if (SHFL_IS_SYMLINK(attr->mode)) { - inode->i_mode = sbi->o.fmode_set ? sbi->o.fmode : mode; - inode->i_mode &= ~sbi->o.fmask; - inode->i_mode |= S_IFLNK; - inode->i_op = &vboxsf_lnk_iops; - set_nlink(inode, 1); - } else { - inode->i_mode = sbi->o.fmode_set ? sbi->o.fmode : mode; - inode->i_mode &= ~sbi->o.fmask; - inode->i_mode |= S_IFREG; - inode->i_op = &vboxsf_reg_iops; - inode->i_fop = &vboxsf_reg_fops; - set_nlink(inode, 1); - } - - inode->i_uid = sbi->o.uid; - inode->i_gid = sbi->o.gid; - - inode->i_size = info->size; - inode->i_blkbits = 12; - /* i_blocks always in units of 512 bytes! */ - allocated = info->allocated + 511; - do_div(allocated, 512); - inode->i_blocks = allocated; - - inode->i_atime = ns_to_timespec64( - info->access_time.ns_relative_to_unix_epoch); - inode->i_ctime = ns_to_timespec64( - info->change_time.ns_relative_to_unix_epoch); - inode->i_mtime = ns_to_timespec64( - info->modification_time.ns_relative_to_unix_epoch); -} - -int vboxsf_create_at_dentry(struct dentry *dentry, - struct shfl_createparms *params) -{ - struct vboxsf_sbi *sbi = VBOXSF_SBI(dentry->d_sb); - struct shfl_string *path; - int err; - - path