regops.c revision 94c634ca5c75b1f49fa94d7ece217fd16e458731
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync/** @file
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync *
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync * vboxvfs -- VirtualBox Guest Additions for Linux:
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync * Regular file inode and file operations
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync */
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync/*
c97989161fbe75bc14cea477a5443bbf474dd3advboxsync * Copyright (C) 2006-2007 innotek GmbH
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync *
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync * available from http://www.virtualbox.org. This file is free software;
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync * you can redistribute it and/or modify it under the terms of the GNU
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync * General Public License as published by the Free Software Foundation,
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync * in version 2 as it comes in the "COPYING" file of the VirtualBox OSE
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync * distribution. VirtualBox OSE is distributed in the hope that it will
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync * be useful, but WITHOUT ANY WARRANTY of any kind.
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync */
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync/*
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync * Limitations: only COW memory mapping is supported
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync */
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync
e7aa635d70dd0cdf083287ec896fe8cca2775466vboxsync#include "vfsmod.h"
e7aa635d70dd0cdf083287ec896fe8cca2775466vboxsync
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync#define CHUNK_SIZE 4096
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync/* fops */
13fdd42f1fc3e519650037a920e6a54c24973866vboxsyncstatic int
13fdd42f1fc3e519650037a920e6a54c24973866vboxsyncsf_reg_read_aux (const char *caller, struct sf_glob_info *sf_g,
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync struct sf_reg_info *sf_r, void *buf, uint32_t *nread,
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync uint64_t pos)
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync{
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync int rc = vboxCallRead (&client_handle, &sf_g->map, sf_r->handle,
bfbd5e7ef5828bb796fb1070611b906bcb87c08dvboxsync pos, nread, buf, false /* already locked? */);
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync if (VBOX_FAILURE (rc)) {
e7aa635d70dd0cdf083287ec896fe8cca2775466vboxsync LogFunc(("vboxCallRead failed. caller=%s, rc=%Vrc\n",
e7aa635d70dd0cdf083287ec896fe8cca2775466vboxsync caller, rc));
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync return -EPROTO;
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync }
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync return 0;
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync}
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync
13fdd42f1fc3e519650037a920e6a54c24973866vboxsyncstatic ssize_t
13fdd42f1fc3e519650037a920e6a54c24973866vboxsyncsf_reg_read (struct file *file, char *buf, size_t size, loff_t *off)
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync{
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync int err;
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync void *tmp;
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync size_t left = size;
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync ssize_t total_bytes_read = 0;
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync struct inode *inode = file->f_dentry->d_inode;
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync struct sf_glob_info *sf_g = GET_GLOB_INFO (inode->i_sb);
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync struct sf_reg_info *sf_r = file->private_data;
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync loff_t pos = *off;
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync TRACE ();
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync if (!S_ISREG (inode->i_mode)) {
e7aa635d70dd0cdf083287ec896fe8cca2775466vboxsync LogFunc(("read from non regular file %d\n", inode->i_mode));
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync return -EINVAL;
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync }
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync if (!size) {
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync return 0;
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync }
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync tmp = kmalloc (CHUNK_SIZE, GFP_KERNEL);
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync if (!tmp) {
10cc687667528f8e56827010e11a48ac1b0f0eb5vboxsync LogRelFunc(("could not allocate bounce buffer memory %d bytes\n", CHUNK_SIZE));
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync return -ENOMEM;
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync }
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync while (left) {
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync uint32_t to_read, nread;
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync to_read = CHUNK_SIZE;
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync if (to_read > left) {
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync to_read = (uint32_t) left;
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync }
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync nread = to_read;
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync err = sf_reg_read_aux (__func__, sf_g, sf_r, tmp, &nread, pos);
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync if (err) {
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync goto fail;
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync }
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync if (copy_to_user (buf, tmp, nread)) {
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync err = -EFAULT;
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync goto fail;
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync }
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync pos += nread;
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync left -= nread;
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync buf += nread;
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync total_bytes_read += nread;
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync if (nread != to_read) {
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync break;
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync }
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync }
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync *off += total_bytes_read;
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync kfree (tmp);
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync return total_bytes_read;
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync fail:
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync kfree (tmp);
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync return err;
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync}
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync
13fdd42f1fc3e519650037a920e6a54c24973866vboxsyncstatic ssize_t
13fdd42f1fc3e519650037a920e6a54c24973866vboxsyncsf_reg_write (struct file *file, const char *buf, size_t size, loff_t *off)
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync{
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync int err;
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync void *tmp;
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync size_t left = size;
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync ssize_t total_bytes_written = 0;
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync struct inode *inode = file->f_dentry->d_inode;
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync struct sf_inode_info *sf_i = GET_INODE_INFO (inode);
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync struct sf_glob_info *sf_g = GET_GLOB_INFO (inode->i_sb);
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync struct sf_reg_info *sf_r = file->private_data;
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync loff_t pos = *off;
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync TRACE ();
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync BUG_ON (!sf_i);
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync BUG_ON (!sf_g);
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync BUG_ON (!sf_r);
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync if (!S_ISREG (inode->i_mode)) {
e7aa635d70dd0cdf083287ec896fe8cca2775466vboxsync LogFunc(("write to non regular file %d\n", inode->i_mode));
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync return -EINVAL;
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync }
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync if (!size) {
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync return 0;
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync }
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync tmp = kmalloc (CHUNK_SIZE, GFP_KERNEL);
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync if (!tmp) {
10cc687667528f8e56827010e11a48ac1b0f0eb5vboxsync LogRelFunc(("could not allocate bounce buffer memory %d\n", CHUNK_SIZE));
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync return -ENOMEM;
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync }
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync while (left) {
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync int rc;
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync uint32_t to_write, nwritten;
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync to_write = CHUNK_SIZE;
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync if (to_write > left) {
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync to_write = (uint32_t) left;
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync }
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync nwritten = to_write;
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync if (copy_from_user (tmp, buf, to_write)) {
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync err = -EFAULT;
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync goto fail;
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync }
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync rc = vboxCallWrite (&client_handle, &sf_g->map, sf_r->handle,
bfbd5e7ef5828bb796fb1070611b906bcb87c08dvboxsync pos, &nwritten, tmp, false /* already locked? */);
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync if (VBOX_FAILURE (rc)) {
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync err = -EPROTO;
e7aa635d70dd0cdf083287ec896fe8cca2775466vboxsync LogFunc(("vboxCallWrite(%s) failed rc=%Vrc\n",
e7aa635d70dd0cdf083287ec896fe8cca2775466vboxsync sf_i->path->String.utf8, rc));
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync goto fail;
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync }
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync pos += nwritten;
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync left -= nwritten;
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync buf += nwritten;
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync total_bytes_written += nwritten;
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync if (nwritten != to_write) {
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync break;
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync }
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync }
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync#if 1 /* XXX: which way is correct? */
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync *off += total_bytes_written;
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync#else
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync file->f_pos += total_bytes_written;
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync#endif
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync sf_i->force_restat = 1;
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync kfree (tmp);
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync return total_bytes_written;
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync fail:
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync kfree (tmp);
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync return err;
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync}
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync
13fdd42f1fc3e519650037a920e6a54c24973866vboxsyncstatic int
13fdd42f1fc3e519650037a920e6a54c24973866vboxsyncsf_reg_open (struct inode *inode, struct file *file)
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync{
e7aa635d70dd0cdf083287ec896fe8cca2775466vboxsync int rc, rc_linux = 0;
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync struct sf_glob_info *sf_g = GET_GLOB_INFO (inode->i_sb);
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync struct sf_inode_info *sf_i = GET_INODE_INFO (inode);
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync struct sf_reg_info *sf_r;
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync SHFLCREATEPARMS params;
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync TRACE ();
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync BUG_ON (!sf_g);
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync BUG_ON (!sf_i);
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync sf_r = kmalloc (sizeof (*sf_r), GFP_KERNEL);
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync if (!sf_r) {
10cc687667528f8e56827010e11a48ac1b0f0eb5vboxsync LogRelFunc(("could not allocate reg info\n"));
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync return -ENOMEM;
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync }
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync
e7aa635d70dd0cdf083287ec896fe8cca2775466vboxsync LogFunc(("open %s\n", sf_i->path->String.utf8));
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync params.CreateFlags = 0;
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync params.Info.cbObject = 0;
e7aa635d70dd0cdf083287ec896fe8cca2775466vboxsync /* We check this afterwards to find out if the call succeeded
e7aa635d70dd0cdf083287ec896fe8cca2775466vboxsync or failed, as the API does not seem to cleanly distinguish
e7aa635d70dd0cdf083287ec896fe8cca2775466vboxsync error and informational messages. */
e7aa635d70dd0cdf083287ec896fe8cca2775466vboxsync params.Handle = 0;
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync if (file->f_flags & O_CREAT) {
e7aa635d70dd0cdf083287ec896fe8cca2775466vboxsync LogFunc(("O_CREAT set\n"));
e7aa635d70dd0cdf083287ec896fe8cca2775466vboxsync params.CreateFlags |= SHFL_CF_ACT_CREATE_IF_NEW;
27a3e4f5c969628986850d19c8bd11a5e6798838vboxsync /* We ignore O_EXCL, as the Linux kernel seems to call create
27a3e4f5c969628986850d19c8bd11a5e6798838vboxsync beforehand itself, so O_EXCL should always fail. */
10cc687667528f8e56827010e11a48ac1b0f0eb5vboxsync if (file->f_flags & O_TRUNC) {
10cc687667528f8e56827010e11a48ac1b0f0eb5vboxsync LogFunc(("O_TRUNC set\n"));
cf3bdb86f7f5127c75dc4881649667e4d169e97cvboxsync params.CreateFlags |= ( SHFL_CF_ACT_OVERWRITE_IF_EXISTS
cf3bdb86f7f5127c75dc4881649667e4d169e97cvboxsync | SHFL_CF_ACCESS_WRITE);
10cc687667528f8e56827010e11a48ac1b0f0eb5vboxsync }
10cc687667528f8e56827010e11a48ac1b0f0eb5vboxsync else {
10cc687667528f8e56827010e11a48ac1b0f0eb5vboxsync params.CreateFlags |= SHFL_CF_ACT_OPEN_IF_EXISTS;
10cc687667528f8e56827010e11a48ac1b0f0eb5vboxsync }
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync }
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync else {
e7aa635d70dd0cdf083287ec896fe8cca2775466vboxsync params.CreateFlags |= SHFL_CF_ACT_FAIL_IF_NEW;
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync if (file->f_flags & O_TRUNC) {
e7aa635d70dd0cdf083287ec896fe8cca2775466vboxsync LogFunc(("O_TRUNC set\n"));
cf3bdb86f7f5127c75dc4881649667e4d169e97cvboxsync params.CreateFlags |= ( SHFL_CF_ACT_OVERWRITE_IF_EXISTS
cf3bdb86f7f5127c75dc4881649667e4d169e97cvboxsync | SHFL_CF_ACCESS_WRITE);
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync }
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync }
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync if (!(params.CreateFlags & SHFL_CF_ACCESS_READWRITE)) {
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync switch (file->f_flags & O_ACCMODE) {
10cc687667528f8e56827010e11a48ac1b0f0eb5vboxsync case O_RDONLY:
10cc687667528f8e56827010e11a48ac1b0f0eb5vboxsync params.CreateFlags |= SHFL_CF_ACCESS_READ;
10cc687667528f8e56827010e11a48ac1b0f0eb5vboxsync break;
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync
10cc687667528f8e56827010e11a48ac1b0f0eb5vboxsync case O_WRONLY:
10cc687667528f8e56827010e11a48ac1b0f0eb5vboxsync params.CreateFlags |= SHFL_CF_ACCESS_WRITE;
10cc687667528f8e56827010e11a48ac1b0f0eb5vboxsync break;
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync
10cc687667528f8e56827010e11a48ac1b0f0eb5vboxsync case O_RDWR:
10cc687667528f8e56827010e11a48ac1b0f0eb5vboxsync params.CreateFlags |= SHFL_CF_ACCESS_READWRITE;
10cc687667528f8e56827010e11a48ac1b0f0eb5vboxsync break;
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync
10cc687667528f8e56827010e11a48ac1b0f0eb5vboxsync default:
10cc687667528f8e56827010e11a48ac1b0f0eb5vboxsync BUG ();
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync }
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync }
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync
e7aa635d70dd0cdf083287ec896fe8cca2775466vboxsync LogFunc(("sf_reg_open: calling vboxCallCreate, file %s, flags=%d, %#x\n",
e7aa635d70dd0cdf083287ec896fe8cca2775466vboxsync sf_i->path->String.utf8 , file->f_flags, params.CreateFlags));
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync rc = vboxCallCreate (&client_handle, &sf_g->map, sf_i->path, &params);
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync
e7aa635d70dd0cdf083287ec896fe8cca2775466vboxsync if (VBOX_FAILURE (rc)) {
e7aa635d70dd0cdf083287ec896fe8cca2775466vboxsync LogFunc(("vboxCallCreate failed flags=%d,%#x rc=%Vrc\n",
e7aa635d70dd0cdf083287ec896fe8cca2775466vboxsync file->f_flags, params.CreateFlags, rc));
e7aa635d70dd0cdf083287ec896fe8cca2775466vboxsync kfree (sf_r);
10cc687667528f8e56827010e11a48ac1b0f0eb5vboxsync return -RTErrConvertToErrno(rc);
b86cecf790b57671e1caa68592a8fc3c3cf8d01bvboxsync }
b86cecf790b57671e1caa68592a8fc3c3cf8d01bvboxsync
e7aa635d70dd0cdf083287ec896fe8cca2775466vboxsync if (SHFL_HANDLE_NIL == params.Handle) {
e7aa635d70dd0cdf083287ec896fe8cca2775466vboxsync switch (params.Result) {
e7aa635d70dd0cdf083287ec896fe8cca2775466vboxsync case SHFL_PATH_NOT_FOUND:
e7aa635d70dd0cdf083287ec896fe8cca2775466vboxsync case SHFL_FILE_NOT_FOUND:
e7aa635d70dd0cdf083287ec896fe8cca2775466vboxsync rc_linux = -ENOENT;
e7aa635d70dd0cdf083287ec896fe8cca2775466vboxsync break;
e7aa635d70dd0cdf083287ec896fe8cca2775466vboxsync case SHFL_FILE_EXISTS:
e7aa635d70dd0cdf083287ec896fe8cca2775466vboxsync rc_linux = -EEXIST;
e7aa635d70dd0cdf083287ec896fe8cca2775466vboxsync break;
e7aa635d70dd0cdf083287ec896fe8cca2775466vboxsync default:
e7aa635d70dd0cdf083287ec896fe8cca2775466vboxsync break;
e7aa635d70dd0cdf083287ec896fe8cca2775466vboxsync }
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync }
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync sf_i->force_restat = 1;
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync sf_r->handle = params.Handle;
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync file->private_data = sf_r;
e7aa635d70dd0cdf083287ec896fe8cca2775466vboxsync return rc_linux;
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync}
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync
13fdd42f1fc3e519650037a920e6a54c24973866vboxsyncstatic int
13fdd42f1fc3e519650037a920e6a54c24973866vboxsyncsf_reg_release (struct inode *inode, struct file *file)
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync{
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync int rc;
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync struct sf_reg_info *sf_r;
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync struct sf_glob_info *sf_g;
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync TRACE ();
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync sf_g = GET_GLOB_INFO (inode->i_sb);
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync sf_r = file->private_data;
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync BUG_ON (!sf_g);
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync BUG_ON (!sf_r);
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync rc = vboxCallClose (&client_handle, &sf_g->map, sf_r->handle);
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync if (VBOX_FAILURE (rc)) {
e7aa635d70dd0cdf083287ec896fe8cca2775466vboxsync LogFunc(("vboxCallClose failed rc=%Vrc\n", rc));
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync }
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync kfree (sf_r);
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync file->private_data = NULL;
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync return 0;
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync}
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync
13fdd42f1fc3e519650037a920e6a54c24973866vboxsyncstatic struct page *
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync#if LINUX_VERSION_CODE < KERNEL_VERSION (2, 6, 0)
13fdd42f1fc3e519650037a920e6a54c24973866vboxsyncsf_reg_nopage (struct vm_area_struct *vma, unsigned long vaddr, int unused)
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync#define SET_TYPE(t)
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync#else
13fdd42f1fc3e519650037a920e6a54c24973866vboxsyncsf_reg_nopage (struct vm_area_struct *vma, unsigned long vaddr, int *type)
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync#define SET_TYPE(t) *type = (t)
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync#endif
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync{
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync struct page *page;
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync char *buf;
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync loff_t off;
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync uint32_t nread = PAGE_SIZE;
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync int err;
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync struct file *file = vma->vm_file;
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync struct inode *inode = file->f_dentry->d_inode;
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync struct sf_glob_info *sf_g = GET_GLOB_INFO (inode->i_sb);
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync struct sf_reg_info *sf_r = file->private_data;
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync TRACE ();
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync if (vaddr > vma->vm_end) {
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync SET_TYPE (VM_FAULT_SIGBUS);
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync return NOPAGE_SIGBUS;
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync }
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync page = alloc_page (GFP_HIGHUSER);
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync if (!page) {
10cc687667528f8e56827010e11a48ac1b0f0eb5vboxsync LogRelFunc(("failed to allocate page\n"));
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync SET_TYPE (VM_FAULT_OOM);
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync return NOPAGE_OOM;
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync }
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync buf = kmap (page);
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync off = (vaddr - vma->vm_start) + (vma->vm_pgoff << PAGE_SHIFT);
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync err = sf_reg_read_aux (__func__, sf_g, sf_r, buf, &nread, off);
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync if (err) {
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync kunmap (page);
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync put_page (page);
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync SET_TYPE (VM_FAULT_SIGBUS);
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync return NOPAGE_SIGBUS;
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync }
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync BUG_ON (nread > PAGE_SIZE);
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync if (!nread) {
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync#if LINUX_VERSION_CODE < KERNEL_VERSION (2, 6, 0)
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync clear_user_page (page_address (page), vaddr);
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync#else
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync clear_user_page (page_address (page), vaddr, page);
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync#endif
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync }
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync else {
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync memset (buf + nread, 0, PAGE_SIZE - nread);
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync }
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync flush_dcache_page (page);
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync kunmap (page);
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync SET_TYPE (VM_FAULT_MAJOR);
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync return page;
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync}
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync
13fdd42f1fc3e519650037a920e6a54c24973866vboxsyncstatic struct vm_operations_struct sf_vma_ops = {
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync .nopage = sf_reg_nopage
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync};
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync
13fdd42f1fc3e519650037a920e6a54c24973866vboxsyncstatic int
13fdd42f1fc3e519650037a920e6a54c24973866vboxsyncsf_reg_mmap (struct file *file, struct vm_area_struct *vma)
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync{
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync TRACE ();
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync if (vma->vm_flags & VM_SHARED) {
e7aa635d70dd0cdf083287ec896fe8cca2775466vboxsync LogFunc(("shared mmapping not available\n"));
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync return -EINVAL;
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync }
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync vma->vm_ops = &sf_vma_ops;
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync return 0;
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync}
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync
e7aa635d70dd0cdf083287ec896fe8cca2775466vboxsyncstruct file_operations sf_reg_fops = {
8117ff36d9fe9125ec6f520a84a6b37888c39dbcvboxsync .read = sf_reg_read,
8117ff36d9fe9125ec6f520a84a6b37888c39dbcvboxsync .open = sf_reg_open,
8117ff36d9fe9125ec6f520a84a6b37888c39dbcvboxsync .write = sf_reg_write,
8117ff36d9fe9125ec6f520a84a6b37888c39dbcvboxsync .release = sf_reg_release,
8117ff36d9fe9125ec6f520a84a6b37888c39dbcvboxsync .mmap = sf_reg_mmap,
8117ff36d9fe9125ec6f520a84a6b37888c39dbcvboxsync#if LINUX_VERSION_CODE >= KERNEL_VERSION (2, 6, 0)
94c634ca5c75b1f49fa94d7ece217fd16e458731vboxsync# if LINUX_VERSION_CODE >= KERNEL_VERSION (2, 6, 23)
94c634ca5c75b1f49fa94d7ece217fd16e458731vboxsync .splice_read = generic_file_splice_read,
94c634ca5c75b1f49fa94d7ece217fd16e458731vboxsync# else
8117ff36d9fe9125ec6f520a84a6b37888c39dbcvboxsync .sendfile = generic_file_sendfile,
94c634ca5c75b1f49fa94d7ece217fd16e458731vboxsync# endif
8117ff36d9fe9125ec6f520a84a6b37888c39dbcvboxsync .fsync = simple_sync_file,
8117ff36d9fe9125ec6f520a84a6b37888c39dbcvboxsync#endif
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync};
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync/* iops */
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync
e7aa635d70dd0cdf083287ec896fe8cca2775466vboxsyncstruct inode_operations sf_reg_iops = {
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync#if LINUX_VERSION_CODE < KERNEL_VERSION (2, 6, 0)
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync .revalidate = sf_inode_revalidate
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync#else
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync .getattr = sf_getattr
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync#endif
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync};