7bb8e57c34db069013b5348ff72a260d10c41ad1vboxsync/* $Id$ */
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync/** @file
7bb8e57c34db069013b5348ff72a260d10c41ad1vboxsync * vboxsf - VBox Linux Shared Folders, Regular file inode and file operations.
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync */
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync/*
c58f1213e628a545081c70e26c6b67a841cff880vboxsync * Copyright (C) 2006-2012 Oracle Corporation
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
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * General Public License (GPL) as published by the Free Software
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * hope that it will 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
7bb8e57c34db069013b5348ff72a260d10c41ad1vboxsyncstatic void *alloc_bounce_buffer(size_t *tmp_sizep, PRTCCPHYS physp, size_t
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync xfer_size, const char *caller)
7ca4727ba2f9e3703771a308b11cd551f3fca4fdvboxsync{
7ca4727ba2f9e3703771a308b11cd551f3fca4fdvboxsync size_t tmp_size;
7ca4727ba2f9e3703771a308b11cd551f3fca4fdvboxsync void *tmp;
7ca4727ba2f9e3703771a308b11cd551f3fca4fdvboxsync
7ca4727ba2f9e3703771a308b11cd551f3fca4fdvboxsync /* try for big first. */
7ca4727ba2f9e3703771a308b11cd551f3fca4fdvboxsync tmp_size = RT_ALIGN_Z(xfer_size, PAGE_SIZE);
7ca4727ba2f9e3703771a308b11cd551f3fca4fdvboxsync if (tmp_size > 16U*_1K)
7ca4727ba2f9e3703771a308b11cd551f3fca4fdvboxsync tmp_size = 16U*_1K;
0b689b4143f8a4f8fcbc2d80782572b2956c2ff8vboxsync tmp = kmalloc(tmp_size, GFP_KERNEL);
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync if (!tmp)
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync {
7ca4727ba2f9e3703771a308b11cd551f3fca4fdvboxsync /* fall back on a page sized buffer. */
0b689b4143f8a4f8fcbc2d80782572b2956c2ff8vboxsync tmp = kmalloc(PAGE_SIZE, GFP_KERNEL);
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync if (!tmp)
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync {
7ca4727ba2f9e3703771a308b11cd551f3fca4fdvboxsync LogRel(("%s: could not allocate bounce buffer for xfer_size=%zu %s\n", caller, xfer_size));
7ca4727ba2f9e3703771a308b11cd551f3fca4fdvboxsync return NULL;
7ca4727ba2f9e3703771a308b11cd551f3fca4fdvboxsync }
7ca4727ba2f9e3703771a308b11cd551f3fca4fdvboxsync tmp_size = PAGE_SIZE;
7ca4727ba2f9e3703771a308b11cd551f3fca4fdvboxsync }
7ca4727ba2f9e3703771a308b11cd551f3fca4fdvboxsync
7ca4727ba2f9e3703771a308b11cd551f3fca4fdvboxsync *tmp_sizep = tmp_size;
7ca4727ba2f9e3703771a308b11cd551f3fca4fdvboxsync *physp = virt_to_phys(tmp);
7ca4727ba2f9e3703771a308b11cd551f3fca4fdvboxsync return tmp;
7ca4727ba2f9e3703771a308b11cd551f3fca4fdvboxsync}
7ca4727ba2f9e3703771a308b11cd551f3fca4fdvboxsync
7bb8e57c34db069013b5348ff72a260d10c41ad1vboxsyncstatic void free_bounce_buffer(void *tmp)
7ca4727ba2f9e3703771a308b11cd551f3fca4fdvboxsync{
7ca4727ba2f9e3703771a308b11cd551f3fca4fdvboxsync kfree (tmp);
7ca4727ba2f9e3703771a308b11cd551f3fca4fdvboxsync}
7ca4727ba2f9e3703771a308b11cd551f3fca4fdvboxsync
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync/* fops */
60d03c38311c6e4c34add74be472fe2098f52d6evboxsyncstatic int sf_reg_read_aux(const char *caller, struct sf_glob_info *sf_g,
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync struct sf_reg_info *sf_r, void *buf,
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync uint32_t *nread, uint64_t pos)
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync{
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync /** @todo bird: yes, kmap() and kmalloc() input only. Since the buffer is
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync * contiguous in physical memory (kmalloc or single page), we should
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync * use a physical address here to speed things up. */
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync int rc = vboxCallRead(&client_handle, &sf_g->map, sf_r->handle,
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync pos, nread, buf, false /* already locked? */);
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync if (RT_FAILURE(rc))
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync {
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync LogFunc(("vboxCallRead failed. caller=%s, rc=%Rrc\n", caller, rc));
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync return -EPROTO;
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync }
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync return 0;
9afa6c5f4f1d021b1c7d066967ed02037fb14c42vboxsync}
9afa6c5f4f1d021b1c7d066967ed02037fb14c42vboxsync
60d03c38311c6e4c34add74be472fe2098f52d6evboxsyncstatic int sf_reg_write_aux(const char *caller, struct sf_glob_info *sf_g,
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync struct sf_reg_info *sf_r, void *buf,
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync uint32_t *nwritten, uint64_t pos)
9afa6c5f4f1d021b1c7d066967ed02037fb14c42vboxsync{
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync /** @todo bird: yes, kmap() and kmalloc() input only. Since the buffer is
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync * contiguous in physical memory (kmalloc or single page), we should
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync * use a physical address here to speed things up. */
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync int rc = vboxCallWrite(&client_handle, &sf_g->map, sf_r->handle,
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync pos, nwritten, buf, false /* already locked? */);
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync if (RT_FAILURE(rc))
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync {
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync LogFunc(("vboxCallWrite failed. caller=%s, rc=%Rrc\n",
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync caller, rc));
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync return -EPROTO;
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync }
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync return 0;
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync}
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync/**
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync * Read from a regular file.
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync *
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync * @param file the file
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync * @param buf the buffer
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync * @param size length of the buffer
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync * @param off offset within the file
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync * @returns the number of read bytes on success, Linux error code otherwise
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync */
60d03c38311c6e4c34add74be472fe2098f52d6evboxsyncstatic ssize_t sf_reg_read(struct file *file, char *buf, size_t size, loff_t *off)
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync{
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync int err;
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync void *tmp;
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync RTCCPHYS tmp_phys;
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync size_t tmp_size;
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync size_t left = size;
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync ssize_t total_bytes_read = 0;
335339b2f047d0cc077224d3d724b2c3b1a6a383vboxsync struct inode *inode = GET_F_DENTRY(file)->d_inode;
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync struct sf_glob_info *sf_g = GET_GLOB_INFO(inode->i_sb);
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync struct sf_reg_info *sf_r = file->private_data;
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync loff_t pos = *off;
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync TRACE();
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync if (!S_ISREG(inode->i_mode))
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync {
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync LogFunc(("read from non regular file %d\n", inode->i_mode));
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync return -EINVAL;
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync }
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync
ad27e1d5e48ca41245120c331cc88b50464813cevboxsync /** XXX Check read permission according to inode->i_mode! */
aa9eecc1b20f1a9d5ef527d054af454a08879a9dvboxsync
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync if (!size)
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync return 0;
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync
7bb8e57c34db069013b5348ff72a260d10c41ad1vboxsync tmp = alloc_bounce_buffer(&tmp_size, &tmp_phys, size, __PRETTY_FUNCTION__);
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync if (!tmp)
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync return -ENOMEM;
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync while (left)
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync {
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync uint32_t to_read, nread;
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync to_read = tmp_size;
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync if (to_read > left)
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync to_read = (uint32_t) left;
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync nread = to_read;
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync err = sf_reg_read_aux(__func__, sf_g, sf_r, tmp, &nread, pos);
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync if (err)
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync goto fail;
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync if (copy_to_user(buf, tmp, nread))
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync {
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync err = -EFAULT;
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync goto fail;
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync }
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync pos += nread;
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync left -= nread;
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync buf += nread;
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync total_bytes_read += nread;
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync if (nread != to_read)
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync break;
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync }
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync *off += total_bytes_read;
7bb8e57c34db069013b5348ff72a260d10c41ad1vboxsync free_bounce_buffer(tmp);
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync return total_bytes_read;
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync
60d03c38311c6e4c34add74be472fe2098f52d6evboxsyncfail:
7bb8e57c34db069013b5348ff72a260d10c41ad1vboxsync free_bounce_buffer(tmp);
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync return err;
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync}
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync/**
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync * Write to a regular file.
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync *
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync * @param file the file
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync * @param buf the buffer
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync * @param size length of the buffer
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync * @param off offset within the file
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync * @returns the number of written bytes on success, Linux error code otherwise
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync */
60d03c38311c6e4c34add74be472fe2098f52d6evboxsyncstatic ssize_t sf_reg_write(struct file *file, const char *buf, size_t size, loff_t *off)
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync{
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync int err;
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync void *tmp;
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync RTCCPHYS tmp_phys;
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync size_t tmp_size;
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync size_t left = size;
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync ssize_t total_bytes_written = 0;
335339b2f047d0cc077224d3d724b2c3b1a6a383vboxsync struct inode *inode = GET_F_DENTRY(file)->d_inode;
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync struct sf_inode_info *sf_i = GET_INODE_INFO(inode);
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync struct sf_glob_info *sf_g = GET_GLOB_INFO(inode->i_sb);
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync struct sf_reg_info *sf_r = file->private_data;
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync loff_t pos;
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync TRACE();
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync BUG_ON(!sf_i);
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync BUG_ON(!sf_g);
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync BUG_ON(!sf_r);
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync if (!S_ISREG(inode->i_mode))
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync {
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync LogFunc(("write to non regular file %d\n", inode->i_mode));
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync return -EINVAL;
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync }
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync pos = *off;
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync if (file->f_flags & O_APPEND)
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync {
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync pos = inode->i_size;
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync *off = pos;
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync }
a3b6aa2acb28aef68fc52cff45df4ac6d4a2655dvboxsync
ad27e1d5e48ca41245120c331cc88b50464813cevboxsync /** XXX Check write permission according to inode->i_mode! */
aa9eecc1b20f1a9d5ef527d054af454a08879a9dvboxsync
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync if (!size)
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync return 0;
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync
7bb8e57c34db069013b5348ff72a260d10c41ad1vboxsync tmp = alloc_bounce_buffer(&tmp_size, &tmp_phys, size, __PRETTY_FUNCTION__);
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync if (!tmp)
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync return -ENOMEM;
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync while (left)
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync {
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync uint32_t to_write, nwritten;
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync to_write = tmp_size;
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync if (to_write > left)
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync to_write = (uint32_t) left;
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync nwritten = to_write;
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync if (copy_from_user(tmp, buf, to_write))
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync {
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync err = -EFAULT;
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync goto fail;
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync }
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync
7ca4727ba2f9e3703771a308b11cd551f3fca4fdvboxsync#if 1
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync if (VbglR0CanUsePhysPageList())
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync {
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync err = VbglR0SfWritePhysCont(&client_handle, &sf_g->map, sf_r->handle,
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync pos, &nwritten, tmp_phys);
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync err = RT_FAILURE(err) ? -EPROTO : 0;
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync }
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync else
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync#endif
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync err = sf_reg_write_aux(__func__, sf_g, sf_r, tmp, &nwritten, pos);
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync if (err)
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync goto fail;
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync pos += nwritten;
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync left -= nwritten;
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync buf += nwritten;
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync total_bytes_written += nwritten;
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync if (nwritten != to_write)
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync break;
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync }
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync *off += total_bytes_written;
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync if (*off > inode->i_size)
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync inode->i_size = *off;
1804358f1a69e31cd294ba3035ef187d18d248e5vboxsync
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync sf_i->force_restat = 1;
7bb8e57c34db069013b5348ff72a260d10c41ad1vboxsync free_bounce_buffer(tmp);
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync return total_bytes_written;
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync
60d03c38311c6e4c34add74be472fe2098f52d6evboxsyncfail:
7bb8e57c34db069013b5348ff72a260d10c41ad1vboxsync free_bounce_buffer(tmp);
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync return err;
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync}
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync/**
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync * Open a regular file.
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync *
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync * @param inode the inode
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync * @param file the file
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync * @returns 0 on success, Linux error code otherwise
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync */
60d03c38311c6e4c34add74be472fe2098f52d6evboxsyncstatic int sf_reg_open(struct inode *inode, struct file *file)
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync{
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync int rc, rc_linux = 0;
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync struct sf_glob_info *sf_g = GET_GLOB_INFO(inode->i_sb);
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync struct sf_inode_info *sf_i = GET_INODE_INFO(inode);
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync struct sf_reg_info *sf_r;
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync SHFLCREATEPARMS params;
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync TRACE();
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync BUG_ON(!sf_g);
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync BUG_ON(!sf_i);
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync LogFunc(("open %s\n", sf_i->path->String.utf8));
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync sf_r = kmalloc(sizeof(*sf_r), GFP_KERNEL);
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync if (!sf_r)
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync {
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync LogRelFunc(("could not allocate reg info\n"));
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync return -ENOMEM;
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync }
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync /* Already open? */
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync if (sf_i->handle != SHFL_HANDLE_NIL)
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync {
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync /*
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync * This inode was created with sf_create_aux(). Check the CreateFlags:
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync * O_CREAT, O_TRUNC: inherent true (file was just created). Not sure
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync * about the access flags (SHFL_CF_ACCESS_*).
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync */
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync sf_i->force_restat = 1;
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync sf_r->handle = sf_i->handle;
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync sf_i->handle = SHFL_HANDLE_NIL;
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync sf_i->file = file;
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync file->private_data = sf_r;
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync return 0;
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync }
96d4e352756f2b2d51db5c68480ca82a1cb21e4fvboxsync
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync RT_ZERO(params);
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync params.Handle = SHFL_HANDLE_NIL;
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync /* We check the value of params.Handle afterwards to find out if
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync * the call succeeded or failed, as the API does not seem to cleanly
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync * distinguish error and informational messages.
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync *
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync * Furthermore, we must set params.Handle to SHFL_HANDLE_NIL to
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync * make the shared folders host service use our fMode parameter */
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync if (file->f_flags & O_CREAT)
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync {
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync LogFunc(("O_CREAT set\n"));
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync params.CreateFlags |= SHFL_CF_ACT_CREATE_IF_NEW;
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync /* We ignore O_EXCL, as the Linux kernel seems to call create
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync beforehand itself, so O_EXCL should always fail. */
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync if (file->f_flags & O_TRUNC)
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync {
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync LogFunc(("O_TRUNC set\n"));
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync params.CreateFlags |= ( SHFL_CF_ACT_OVERWRITE_IF_EXISTS
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync | SHFL_CF_ACCESS_WRITE);
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync }
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync else
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync params.CreateFlags |= SHFL_CF_ACT_OPEN_IF_EXISTS;
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync }
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync else
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync {
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync params.CreateFlags |= SHFL_CF_ACT_FAIL_IF_NEW;
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync if (file->f_flags & O_TRUNC)
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync {
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync LogFunc(("O_TRUNC set\n"));
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync params.CreateFlags |= ( SHFL_CF_ACT_OVERWRITE_IF_EXISTS
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync | SHFL_CF_ACCESS_WRITE);
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync }
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync }
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync if (!(params.CreateFlags & SHFL_CF_ACCESS_READWRITE))
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync {
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync switch (file->f_flags & O_ACCMODE)
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync {
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync case O_RDONLY:
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync params.CreateFlags |= SHFL_CF_ACCESS_READ;
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync break;
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync case O_WRONLY:
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync params.CreateFlags |= SHFL_CF_ACCESS_WRITE;
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync break;
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync case O_RDWR:
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync params.CreateFlags |= SHFL_CF_ACCESS_READWRITE;
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync break;
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync default:
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync BUG ();
5bbfeb753c086a6a632a0c312ff28cadad13f14fvboxsync }
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync }
5bbfeb753c086a6a632a0c312ff28cadad13f14fvboxsync
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync if (file->f_flags & O_APPEND)
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync {
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync LogFunc(("O_APPEND set\n"));
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync params.CreateFlags |= SHFL_CF_ACCESS_APPEND;
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync }
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync params.Info.Attr.fMode = inode->i_mode;
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync LogFunc(("sf_reg_open: calling vboxCallCreate, file %s, flags=%#x, %#x\n",
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync sf_i->path->String.utf8 , file->f_flags, params.CreateFlags));
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync rc = vboxCallCreate(&client_handle, &sf_g->map, sf_i->path, &params);
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync if (RT_FAILURE(rc))
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync {
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync LogFunc(("vboxCallCreate failed flags=%d,%#x rc=%Rrc\n",
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync file->f_flags, params.CreateFlags, rc));
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync kfree(sf_r);
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync return -RTErrConvertToErrno(rc);
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync }
b86cecf790b57671e1caa68592a8fc3c3cf8d01bvboxsync
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync if (SHFL_HANDLE_NIL == params.Handle)
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync {
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync switch (params.Result)
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync {
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync case SHFL_PATH_NOT_FOUND:
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync case SHFL_FILE_NOT_FOUND:
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync rc_linux = -ENOENT;
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync break;
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync case SHFL_FILE_EXISTS:
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync rc_linux = -EEXIST;
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync break;
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync default:
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync break;
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync }
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync }
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync sf_i->force_restat = 1;
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync sf_r->handle = params.Handle;
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync sf_i->file = file;
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync file->private_data = sf_r;
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync return rc_linux;
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync}
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync/**
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync * Close a regular file.
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync *
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync * @param inode the inode
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync * @param file the file
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync * @returns 0 on success, Linux error code otherwise
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync */
60d03c38311c6e4c34add74be472fe2098f52d6evboxsyncstatic int sf_reg_release(struct inode *inode, struct file *file)
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync{
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync int rc;
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync struct sf_reg_info *sf_r;
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync struct sf_glob_info *sf_g;
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync struct sf_inode_info *sf_i = GET_INODE_INFO(inode);
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync TRACE();
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync sf_g = GET_GLOB_INFO(inode->i_sb);
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync sf_r = file->private_data;
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync BUG_ON(!sf_g);
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync BUG_ON(!sf_r);
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync
ea9a25c873380b5352595e122e40a3a6935e4ca1vboxsync#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 25)
d34b48c33206883798ebbcf53ad8a3b9d81b9b43vboxsync /* See the smbfs source (file.c). mmap in particular can cause data to be
ea9a25c873380b5352595e122e40a3a6935e4ca1vboxsync * written to the file after it is closed, which we can't cope with. We
ea9a25c873380b5352595e122e40a3a6935e4ca1vboxsync * copy and paste the body of filemap_write_and_wait() here as it was not
ea9a25c873380b5352595e122e40a3a6935e4ca1vboxsync * defined before 2.6.6 and not exported until quite a bit later. */
ea9a25c873380b5352595e122e40a3a6935e4ca1vboxsync /* filemap_write_and_wait(inode->i_mapping); */
ea9a25c873380b5352595e122e40a3a6935e4ca1vboxsync if ( inode->i_mapping->nrpages
ea9a25c873380b5352595e122e40a3a6935e4ca1vboxsync && filemap_fdatawrite(inode->i_mapping) != -EIO)
ea9a25c873380b5352595e122e40a3a6935e4ca1vboxsync filemap_fdatawait(inode->i_mapping);
8a613121a40ec69fb1d24abb8fbe3a3811fd8bd8vboxsync#endif
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync rc = vboxCallClose(&client_handle, &sf_g->map, sf_r->handle);
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync if (RT_FAILURE(rc))
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync LogFunc(("vboxCallClose failed rc=%Rrc\n", rc));
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync kfree(sf_r);
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync sf_i->file = NULL;
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync sf_i->handle = SHFL_HANDLE_NIL;
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync file->private_data = NULL;
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync return 0;
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync}
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync
0b689b4143f8a4f8fcbc2d80782572b2956c2ff8vboxsync#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 25)
60d03c38311c6e4c34add74be472fe2098f52d6evboxsyncstatic int sf_reg_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
0b689b4143f8a4f8fcbc2d80782572b2956c2ff8vboxsync#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
60d03c38311c6e4c34add74be472fe2098f52d6evboxsyncstatic struct page *sf_reg_nopage(struct vm_area_struct *vma, unsigned long vaddr, int *type)
44149cdca56c8367be796989ef98416272db7681vboxsync# define SET_TYPE(t) *type = (t)
335339b2f047d0cc077224d3d724b2c3b1a6a383vboxsync#else /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0) */
60d03c38311c6e4c34add74be472fe2098f52d6evboxsyncstatic struct page *sf_reg_nopage(struct vm_area_struct *vma, unsigned long vaddr, int unused)
44149cdca56c8367be796989ef98416272db7681vboxsync# define SET_TYPE(t)
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync#endif
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync{
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync struct page *page;
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync char *buf;
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync loff_t off;
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync uint32_t nread = PAGE_SIZE;
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync int err;
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync struct file *file = vma->vm_file;
335339b2f047d0cc077224d3d724b2c3b1a6a383vboxsync struct inode *inode = GET_F_DENTRY(file)->d_inode;
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync struct sf_glob_info *sf_g = GET_GLOB_INFO(inode->i_sb);
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync struct sf_reg_info *sf_r = file->private_data;
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync TRACE();
0b689b4143f8a4f8fcbc2d80782572b2956c2ff8vboxsync#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 25)
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync if (vmf->pgoff > vma->vm_end)
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync return VM_FAULT_SIGBUS;
44149cdca56c8367be796989ef98416272db7681vboxsync#else
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync if (vaddr > vma->vm_end)
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync {
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync SET_TYPE(VM_FAULT_SIGBUS);
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync return NOPAGE_SIGBUS;
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync }
44149cdca56c8367be796989ef98416272db7681vboxsync#endif
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync
1bf70aeaad14c047c2b006602463761663c0a61dvboxsync /* Don't use GFP_HIGHUSER as long as sf_reg_read_aux() calls vboxCallRead()
1bf70aeaad14c047c2b006602463761663c0a61dvboxsync * which works on virtual addresses. On Linux cannot reliably determine the
1bf70aeaad14c047c2b006602463761663c0a61dvboxsync * physical address for high memory, see rtR0MemObjNativeLockKernel(). */
1bf70aeaad14c047c2b006602463761663c0a61dvboxsync page = alloc_page(GFP_USER);
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync if (!page) {
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync LogRelFunc(("failed to allocate page\n"));
0b689b4143f8a4f8fcbc2d80782572b2956c2ff8vboxsync#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 25)
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync return VM_FAULT_OOM;
44149cdca56c8367be796989ef98416272db7681vboxsync#else
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync SET_TYPE(VM_FAULT_OOM);
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync return NOPAGE_OOM;
44149cdca56c8367be796989ef98416272db7681vboxsync#endif
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync }
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync buf = kmap(page);
0b689b4143f8a4f8fcbc2d80782572b2956c2ff8vboxsync#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 25)
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync off = (vmf->pgoff << PAGE_SHIFT);
44149cdca56c8367be796989ef98416272db7681vboxsync#else
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync off = (vaddr - vma->vm_start) + (vma->vm_pgoff << PAGE_SHIFT);
44149cdca56c8367be796989ef98416272db7681vboxsync#endif
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync err = sf_reg_read_aux(__func__, sf_g, sf_r, buf, &nread, off);
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync if (err)
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync {
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync kunmap(page);
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync put_page(page);
0b689b4143f8a4f8fcbc2d80782572b2956c2ff8vboxsync#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 25)
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync return VM_FAULT_SIGBUS;
44149cdca56c8367be796989ef98416272db7681vboxsync#else
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync SET_TYPE(VM_FAULT_SIGBUS);
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync return NOPAGE_SIGBUS;
44149cdca56c8367be796989ef98416272db7681vboxsync#endif
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync }
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync BUG_ON (nread > PAGE_SIZE);
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync if (!nread)
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync {
0b689b4143f8a4f8fcbc2d80782572b2956c2ff8vboxsync#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 25)
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync clear_user_page(page_address(page), vmf->pgoff, page);
0b689b4143f8a4f8fcbc2d80782572b2956c2ff8vboxsync#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync clear_user_page(page_address(page), vaddr, page);
44149cdca56c8367be796989ef98416272db7681vboxsync#else
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync clear_user_page(page_address(page), vaddr);
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync#endif
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync }
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync else
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync memset(buf + nread, 0, PAGE_SIZE - nread);
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync flush_dcache_page(page);
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync kunmap(page);
0b689b4143f8a4f8fcbc2d80782572b2956c2ff8vboxsync#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 25)
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync vmf->page = page;
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync return 0;
44149cdca56c8367be796989ef98416272db7681vboxsync#else
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync SET_TYPE(VM_FAULT_MAJOR);
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync return page;
44149cdca56c8367be796989ef98416272db7681vboxsync#endif
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync}
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync
60d03c38311c6e4c34add74be472fe2098f52d6evboxsyncstatic struct vm_operations_struct sf_vma_ops =
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync{
0b689b4143f8a4f8fcbc2d80782572b2956c2ff8vboxsync#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 25)
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync .fault = sf_reg_fault
44149cdca56c8367be796989ef98416272db7681vboxsync#else
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync .nopage = sf_reg_nopage
44149cdca56c8367be796989ef98416272db7681vboxsync#endif
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync};
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync
60d03c38311c6e4c34add74be472fe2098f52d6evboxsyncstatic int sf_reg_mmap(struct file *file, struct vm_area_struct *vma)
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync{
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync TRACE();
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync if (vma->vm_flags & VM_SHARED)
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync {
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync LogFunc(("shared mmapping not available\n"));
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync return -EINVAL;
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync }
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync vma->vm_ops = &sf_vma_ops;
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync return 0;
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync}
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync
60d03c38311c6e4c34add74be472fe2098f52d6evboxsyncstruct file_operations sf_reg_fops =
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync{
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync .read = sf_reg_read,
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync .open = sf_reg_open,
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync .write = sf_reg_write,
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync .release = sf_reg_release,
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync .mmap = sf_reg_mmap,
0b689b4143f8a4f8fcbc2d80782572b2956c2ff8vboxsync#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
0b689b4143f8a4f8fcbc2d80782572b2956c2ff8vboxsync# if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 23)
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync .splice_read = generic_file_splice_read,
94c634ca5c75b1f49fa94d7ece217fd16e458731vboxsync# else
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync .sendfile = generic_file_sendfile,
94c634ca5c75b1f49fa94d7ece217fd16e458731vboxsync# endif
e2d7a52233db3aca34e194f301967eb0019da8c6vboxsync# if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0)
e2d7a52233db3aca34e194f301967eb0019da8c6vboxsync .read_iter = generic_file_read_iter,
e2d7a52233db3aca34e194f301967eb0019da8c6vboxsync .write_iter = generic_file_write_iter,
e2d7a52233db3aca34e194f301967eb0019da8c6vboxsync# else
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync .aio_read = generic_file_aio_read,
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync .aio_write = generic_file_aio_write,
e2d7a52233db3aca34e194f301967eb0019da8c6vboxsync# endif
0b689b4143f8a4f8fcbc2d80782572b2956c2ff8vboxsync# if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35)
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync .fsync = noop_fsync,
81fb43e9556b811acb73526faa0f9ab904da18d4vboxsync# else
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync .fsync = simple_sync_file,
81fb43e9556b811acb73526faa0f9ab904da18d4vboxsync# endif
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync .llseek = generic_file_llseek,
8117ff36d9fe9125ec6f520a84a6b37888c39dbcvboxsync#endif
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync};
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync
60d03c38311c6e4c34add74be472fe2098f52d6evboxsyncstruct inode_operations sf_reg_iops =
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync{
0b689b4143f8a4f8fcbc2d80782572b2956c2ff8vboxsync#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0)
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync .revalidate = sf_inode_revalidate
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync#else
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync .getattr = sf_getattr,
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync .setattr = sf_setattr
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync#endif
13fdd42f1fc3e519650037a920e6a54c24973866vboxsync};
1a36a5b9d31d559ea3668e78e981ee4423515db0vboxsync
1a36a5b9d31d559ea3668e78e981ee4423515db0vboxsync
0b689b4143f8a4f8fcbc2d80782572b2956c2ff8vboxsync#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
60d03c38311c6e4c34add74be472fe2098f52d6evboxsyncstatic int sf_readpage(struct file *file, struct page *page)
1a36a5b9d31d559ea3668e78e981ee4423515db0vboxsync{
335339b2f047d0cc077224d3d724b2c3b1a6a383vboxsync struct inode *inode = GET_F_DENTRY(file)->d_inode;
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync struct sf_glob_info *sf_g = GET_GLOB_INFO(inode->i_sb);
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync struct sf_reg_info *sf_r = file->private_data;
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync uint32_t nread = PAGE_SIZE;
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync char *buf;
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync loff_t off = ((loff_t)page->index) << PAGE_SHIFT;
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync int ret;
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync TRACE();
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync buf = kmap(page);
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync ret = sf_reg_read_aux(__func__, sf_g, sf_r, buf, &nread, off);
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync if (ret)
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync {
0b689b4143f8a4f8fcbc2d80782572b2956c2ff8vboxsync kunmap(page);
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync if (PageLocked(page))
1a36a5b9d31d559ea3668e78e981ee4423515db0vboxsync unlock_page(page);
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync return ret;
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync }
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync BUG_ON(nread > PAGE_SIZE);
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync memset(&buf[nread], 0, PAGE_SIZE - nread);
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync flush_dcache_page(page);
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync kunmap(page);
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync SetPageUptodate(page);
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync unlock_page(page);
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync return 0;
1a36a5b9d31d559ea3668e78e981ee4423515db0vboxsync}
1a36a5b9d31d559ea3668e78e981ee4423515db0vboxsync
9afa6c5f4f1d021b1c7d066967ed02037fb14c42vboxsyncstatic int
9afa6c5f4f1d021b1c7d066967ed02037fb14c42vboxsyncsf_writepage(struct page *page, struct writeback_control *wbc)
9afa6c5f4f1d021b1c7d066967ed02037fb14c42vboxsync{
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync struct address_space *mapping = page->mapping;
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync struct inode *inode = mapping->host;
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync struct sf_glob_info *sf_g = GET_GLOB_INFO(inode->i_sb);
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync struct sf_inode_info *sf_i = GET_INODE_INFO(inode);
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync struct file *file = sf_i->file;
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync struct sf_reg_info *sf_r = file->private_data;
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync char *buf;
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync uint32_t nwritten = PAGE_SIZE;
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync int end_index = inode->i_size >> PAGE_SHIFT;
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync loff_t off = ((loff_t) page->index) << PAGE_SHIFT;
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync int err;
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync TRACE();
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync if (page->index >= end_index)
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync nwritten = inode->i_size & (PAGE_SIZE-1);
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync buf = kmap(page);
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync err = sf_reg_write_aux(__func__, sf_g, sf_r, buf, &nwritten, off);
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync if (err < 0)
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync {
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync ClearPageUptodate(page);
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync goto out;
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync }
9afa6c5f4f1d021b1c7d066967ed02037fb14c42vboxsync
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync if (off > inode->i_size)
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync inode->i_size = off;
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync if (PageError(page))
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync ClearPageError(page);
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync err = 0;
9afa6c5f4f1d021b1c7d066967ed02037fb14c42vboxsync
9afa6c5f4f1d021b1c7d066967ed02037fb14c42vboxsyncout:
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync kunmap(page);
9afa6c5f4f1d021b1c7d066967ed02037fb14c42vboxsync
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync unlock_page(page);
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync return err;
9afa6c5f4f1d021b1c7d066967ed02037fb14c42vboxsync}
9afa6c5f4f1d021b1c7d066967ed02037fb14c42vboxsync
0b689b4143f8a4f8fcbc2d80782572b2956c2ff8vboxsync# if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24)
60d03c38311c6e4c34add74be472fe2098f52d6evboxsyncint sf_write_begin(struct file *file, struct address_space *mapping, loff_t pos,
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync unsigned len, unsigned flags, struct page **pagep, void **fsdata)
9afa6c5f4f1d021b1c7d066967ed02037fb14c42vboxsync{
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync TRACE();
9afa6c5f4f1d021b1c7d066967ed02037fb14c42vboxsync
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync return simple_write_begin(file, mapping, pos, len, flags, pagep, fsdata);
9afa6c5f4f1d021b1c7d066967ed02037fb14c42vboxsync}
9afa6c5f4f1d021b1c7d066967ed02037fb14c42vboxsync
60d03c38311c6e4c34add74be472fe2098f52d6evboxsyncint sf_write_end(struct file *file, struct address_space *mapping, loff_t pos,
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync unsigned len, unsigned copied, struct page *page, void *fsdata)
9afa6c5f4f1d021b1c7d066967ed02037fb14c42vboxsync{
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync struct inode *inode = mapping->host;
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync struct sf_glob_info *sf_g = GET_GLOB_INFO(inode->i_sb);
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync struct sf_reg_info *sf_r = file->private_data;
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync void *buf;
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync unsigned from = pos & (PAGE_SIZE - 1);
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync uint32_t nwritten = len;
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync int err;
9afa6c5f4f1d021b1c7d066967ed02037fb14c42vboxsync
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync TRACE();
9afa6c5f4f1d021b1c7d066967ed02037fb14c42vboxsync
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync buf = kmap(page);
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync err = sf_reg_write_aux(__func__, sf_g, sf_r, buf+from, &nwritten, pos);
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync kunmap(page);
9afa6c5f4f1d021b1c7d066967ed02037fb14c42vboxsync
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync if (!PageUptodate(page) && err == PAGE_SIZE)
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync SetPageUptodate(page);
9afa6c5f4f1d021b1c7d066967ed02037fb14c42vboxsync
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync if (err >= 0) {
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync pos += nwritten;
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync if (pos > inode->i_size)
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync inode->i_size = pos;
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync }
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync unlock_page(page);
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync page_cache_release(page);
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync return nwritten;
9afa6c5f4f1d021b1c7d066967ed02037fb14c42vboxsync}
9afa6c5f4f1d021b1c7d066967ed02037fb14c42vboxsync
9afa6c5f4f1d021b1c7d066967ed02037fb14c42vboxsync# endif /* KERNEL_VERSION >= 2.6.24 */
9afa6c5f4f1d021b1c7d066967ed02037fb14c42vboxsync
60d03c38311c6e4c34add74be472fe2098f52d6evboxsyncstruct address_space_operations sf_reg_aops =
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync{
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync .readpage = sf_readpage,
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync .writepage = sf_writepage,
0b689b4143f8a4f8fcbc2d80782572b2956c2ff8vboxsync# if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24)
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync .write_begin = sf_write_begin,
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync .write_end = sf_write_end,
1a36a5b9d31d559ea3668e78e981ee4423515db0vboxsync# else
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync .prepare_write = simple_prepare_write,
60d03c38311c6e4c34add74be472fe2098f52d6evboxsync .commit_write = simple_commit_write,
1a36a5b9d31d559ea3668e78e981ee4423515db0vboxsync# endif
1a36a5b9d31d559ea3668e78e981ee4423515db0vboxsync};
1a36a5b9d31d559ea3668e78e981ee4423515db0vboxsync#endif