regops.c revision c97989161fbe75bc14cea477a5443bbf474dd3ad
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 * If you received this file as part of a commercial VirtualBox
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync * distribution, then only the terms of your commercial VirtualBox
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync * license agreement apply instead of the previous paragraph.
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync */
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync/*
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync * Limitations: only COW memory mapping is supported
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync */
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync
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,
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync pos, nread, buf);
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync if (VBOX_FAILURE (rc)) {
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync elog3 ("%s: %s: vboxCallRead failed rc=%d\n",
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync caller, __func__, 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)) {
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync elog ("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) {
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync elog ("could not allocate bounce buffer memory %u bytes\n",
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync 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)) {
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync elog ("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) {
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync elog ("could not allocate bounce buffer memory %u bytes\n",
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync 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,
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync pos, &nwritten, tmp);
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync if (VBOX_FAILURE (rc)) {
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync err = -EPROTO;
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync elog ("vboxCallWrite(%s) failed rc=%d\n",
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync 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{
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync int rc;
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) {
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync elog2 ("could not allocate reg info\n");
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync return -ENOMEM;
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync }
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync#if 0
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync printk ("open %s\n", sf_i->path->String.utf8);
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync#endif
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync params.CreateFlags = 0;
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync params.Info.cbObject = 0;
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync if (file->f_flags & O_CREAT) {
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync if (file->f_flags & O_EXCL) {
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync params.CreateFlags |= SHFL_CF_ACCESS_READWRITE;
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync params.CreateFlags |= SHFL_CF_ACT_FAIL_IF_EXISTS;
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync }
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync else {
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync params.CreateFlags |= SHFL_CF_ACT_CREATE_IF_NEW;
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync params.CreateFlags |= SHFL_CF_ACCESS_READWRITE;
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync if (file->f_flags & O_TRUNC) {
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync params.CreateFlags |= SHFL_CF_ACT_OVERWRITE_IF_EXISTS;
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync }
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync else {
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync params.CreateFlags |= SHFL_CF_ACT_OPEN_IF_EXISTS;
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync }
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync }
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync }
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync else {
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync if (file->f_flags & O_TRUNC) {
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync params.CreateFlags |= SHFL_CF_ACCESS_READWRITE;
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync params.CreateFlags |= SHFL_CF_ACT_OVERWRITE_IF_EXISTS;
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync }
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync else {
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync params.CreateFlags |= SHFL_CF_ACT_FAIL_IF_NEW;
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync }
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync }
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync if (!(params.CreateFlags & SHFL_CF_ACCESS_READWRITE)) {
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync switch (file->f_flags & O_ACCMODE) {
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync case O_RDONLY:
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync params.CreateFlags |= SHFL_CF_ACCESS_READ;
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync break;
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync case O_WRONLY:
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync params.CreateFlags |= SHFL_CF_ACCESS_WRITE;
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync break;
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync case O_RDWR:
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync params.CreateFlags |= SHFL_CF_ACCESS_READWRITE;
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync break;
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync default:
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync BUG ();
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync }
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync }
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync rc = vboxCallCreate (&client_handle, &sf_g->map, sf_i->path, &params);
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync /* XXX: here i probably should check rc and convert some values to
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync EEXISTS ENOENT etc */
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync if (VBOX_FAILURE (rc)) {
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync elog ("vboxCallCreate failed flags=%d,%#x rc=%d\n",
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync file->f_flags, params.CreateFlags, rc);
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync kfree (sf_r);
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync return -EPROTO;
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync }
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync sf_i->force_restat = 1;
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync sf_r->handle = params.Handle;
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync file->private_data = sf_r;
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync return 0;
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)) {
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync elog ("vboxCallClose failed rc=%d\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) {
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync elog2 ("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) {
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync elog2 ("shared mmapping not available\n");
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync return -EINVAL;
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync }
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync vma->vm_ops = &sf_vma_ops;
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync return 0;
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync}
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync
13fdd42f1fc3e519650037a920e6a54c24973866vboxsyncstatic struct file_operations sf_reg_fops = {
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync .read = sf_reg_read,
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync .open = sf_reg_open,
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync .write = sf_reg_write,
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync .release = sf_reg_release,
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync .mmap = sf_reg_mmap
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync};
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync/* iops */
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync
13fdd42f1fc3e519650037a920e6a54c24973866vboxsyncstatic struct 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};