1403063c7e0c0a072d59e323b66068b06278fb9avboxsync/** @file
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync * VirtualBox File System for Solaris Guests, vnode implementation.
35473cad6d5d5b57348c66f0cfdd7d51d6071ee7vboxsync * Portions contributed by: Ronald.
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync */
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync/*
76110d8ef23142ec3bcab1f50622858bdb55c76dvboxsync * Copyright (C) 2009-2014 Oracle Corporation
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync *
fcae7923a3c756b333f1e33eba002edf4448fb54vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
fcae7923a3c756b333f1e33eba002edf4448fb54vboxsync * available from http://www.virtualbox.org. This file is free software;
fcae7923a3c756b333f1e33eba002edf4448fb54vboxsync * you can redistribute it and/or modify it under the terms of the GNU
fcae7923a3c756b333f1e33eba002edf4448fb54vboxsync * General Public License (GPL) as published by the Free Software
fcae7923a3c756b333f1e33eba002edf4448fb54vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
fcae7923a3c756b333f1e33eba002edf4448fb54vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
fcae7923a3c756b333f1e33eba002edf4448fb54vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
f001425d2b0a661d4cd1f7ea07b4e7454538c829vboxsync *
f001425d2b0a661d4cd1f7ea07b4e7454538c829vboxsync * The contents of this file may alternatively be used under the terms
f001425d2b0a661d4cd1f7ea07b4e7454538c829vboxsync * of the Common Development and Distribution License Version 1.0
f001425d2b0a661d4cd1f7ea07b4e7454538c829vboxsync * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
f001425d2b0a661d4cd1f7ea07b4e7454538c829vboxsync * VirtualBox OSE distribution, in which case the provisions of the
f001425d2b0a661d4cd1f7ea07b4e7454538c829vboxsync * CDDL are applicable instead of those of the GPL.
f001425d2b0a661d4cd1f7ea07b4e7454538c829vboxsync *
f001425d2b0a661d4cd1f7ea07b4e7454538c829vboxsync * You may elect to license modified versions of this file under the
f001425d2b0a661d4cd1f7ea07b4e7454538c829vboxsync * terms and conditions of either the GPL or the CDDL or both.
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync */
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync/*
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync * Shared Folder File System is used from Solaris when run as a guest operating
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync * system on VirtualBox, though is meant to be usable with any hypervisor that
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync * can provide similar functionality. The sffs code handles all the Solaris
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync * specific semantics and relies on a provider module to actually access
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync * directories, files, etc. The provider interfaces are described in
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync * "vboxfs_prov.h" and the module implementing them is shipped as part of the
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync * VirtualBox Guest Additions for Solaris.
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync *
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync * The shared folder file system is similar to a networked file system,
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync * but with some caveats. The sffs code caches minimal information and proxies
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync * out to the provider whenever possible. Here are some things that are
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync * handled in this code and not by the proxy:
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync *
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync * - a way to open ".." from any already open directory
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync * - st_ino numbers
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync * - detecting directory changes that happened on the host.
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync *
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync * The implementation builds a cache of information for every file/directory
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync * ever accessed in all mounted sffs filesystems using sf_node structures.
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync *
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync * This information for both open or closed files can become invalid if
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync * asynchronous changes are made on the host. Solaris should not panic() in
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync * this event, but some file system operations may return unexpected errors.
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync * Information for such directories or files while they have active vnodes
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync * is removed from the regular cache and stored in a "stale" bucket until
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync * the vnode becomes completely inactive.
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync *
691076bd437d5cd23673a24c5ba7d4cd77127354vboxsync * We suppport only read-only mmap (VBOXVFS_WITH_MMAP) i.e. MAP_SHARED,
691076bd437d5cd23673a24c5ba7d4cd77127354vboxsync * MAP_PRIVATE in PROT_READ, this data caching would not be coherent with
691076bd437d5cd23673a24c5ba7d4cd77127354vboxsync * normal simultaneous read()/write() operations, nor will it be coherent
691076bd437d5cd23673a24c5ba7d4cd77127354vboxsync * with data access on the host. Writable mmap(MAP_SHARED) access is not
691076bd437d5cd23673a24c5ba7d4cd77127354vboxsync * implemented, as guaranteeing any kind of coherency with concurrent
691076bd437d5cd23673a24c5ba7d4cd77127354vboxsync * activity on the host would be near impossible with the existing
691076bd437d5cd23673a24c5ba7d4cd77127354vboxsync * interfaces.
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync *
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync * A note about locking. sffs is not a high performance file system.
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync * No fine grained locking is done. The one sffs_lock protects just about
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync * everything.
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync */
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync#include <VBox/log.h>
561b8d2b46fb10887829b7e4d7d29447817adbddvboxsync#include <iprt/asm.h>
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
f65dabff4474710524235022d328b737f174fc1dvboxsync#include <unistd.h>
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync#include <sys/types.h>
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync#include <sys/stat.h>
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync#include <sys/mntent.h>
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync#include <sys/param.h>
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync#include <sys/modctl.h>
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync#include <sys/mount.h>
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync#include <sys/policy.h>
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync#include <sys/atomic.h>
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync#include <sys/sysmacros.h>
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync#include <sys/ddi.h>
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync#include <sys/sunddi.h>
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync#include <sys/vfs.h>
561b8d2b46fb10887829b7e4d7d29447817adbddvboxsync#include <sys/vmsystm.h>
fb4eaa62a6bbeb82a89703d833d39339783feb4avboxsync#include <vm/seg_kpm.h>
fb4eaa62a6bbeb82a89703d833d39339783feb4avboxsync#include <vm/pvn.h>
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync#if !defined(VBOX_VFS_SOLARIS_10U6)
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync#include <sys/vfs_opreg.h>
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync#endif
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync#include <sys/pathname.h>
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync#include <sys/dirent.h>
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync#include <sys/fs_subr.h>
6479169ec893c18a646cec595e4e214492d180f0vboxsync#include <sys/time.h>
96ccbd956a29c56d334c5031974eb88008373148vboxsync#include <sys/cmn_err.h>
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync#include "vboxfs_prov.h"
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync#include "vboxfs_vnode.h"
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync#include "vboxfs_vfs.h"
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
f5857b360ff8ec6877adc641d6c0880795ed7687vboxsync/*
f5857b360ff8ec6877adc641d6c0880795ed7687vboxsync * Solaris 11u1b10 Extended Policy putback CR 7121445 removes secpolicy_vnode_access from sys/policy.h
f5857b360ff8ec6877adc641d6c0880795ed7687vboxsync */
f5857b360ff8ec6877adc641d6c0880795ed7687vboxsync#ifdef VBOX_VFS_EXTENDED_POLICY
f5857b360ff8ec6877adc641d6c0880795ed7687vboxsyncint secpolicy_vnode_access(const cred_t *, vnode_t *, uid_t, mode_t);
f5857b360ff8ec6877adc641d6c0880795ed7687vboxsync#endif
f5857b360ff8ec6877adc641d6c0880795ed7687vboxsync
a2907076474e923411cc5046492a88787ba377fevboxsync#define VBOXVFS_WITH_MMAP
a2907076474e923411cc5046492a88787ba377fevboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsyncstatic struct vnodeops *sffs_ops = NULL;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsynckmutex_t sffs_lock;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsyncstatic avl_tree_t sfnodes;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsyncstatic avl_tree_t stale_sfnodes;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync/*
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync * For now we'll use an I/O buffer that doesn't page fault for VirtualBox
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync * to transfer data into.
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync */
1403063c7e0c0a072d59e323b66068b06278fb9avboxsyncchar *sffs_buffer;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync/*
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync * sfnode_compare() is needed for AVL tree functionality.
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync * The nodes are sorted by mounted filesystem, then path. If the
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync * nodes are stale, the node pointer itself is used to force uniqueness.
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync */
1403063c7e0c0a072d59e323b66068b06278fb9avboxsyncstatic int
1403063c7e0c0a072d59e323b66068b06278fb9avboxsyncsfnode_compare(const void *a, const void *b)
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync{
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync sfnode_t *x = (sfnode_t *)a;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync sfnode_t *y = (sfnode_t *)b;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync int diff;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync if (x->sf_is_stale) {
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync ASSERT(y->sf_is_stale);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync diff = strcmp(x->sf_path, y->sf_path);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync if (diff == 0)
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync diff = (uintptr_t)y - (uintptr_t)x;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync } else {
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync ASSERT(!y->sf_is_stale);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync diff = (uintptr_t)y->sf_sffs - (uintptr_t)x->sf_sffs;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync if (diff == 0)
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync diff = strcmp(x->sf_path, y->sf_path);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync }
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync if (diff < 0)
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync return (-1);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync if (diff > 0)
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync return (1);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync return (0);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync}
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync/*
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync * Construct a new pathname given an sfnode plus an optional tail component.
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync * This handles ".." and "."
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync */
1403063c7e0c0a072d59e323b66068b06278fb9avboxsyncstatic char *
1403063c7e0c0a072d59e323b66068b06278fb9avboxsyncsfnode_construct_path(sfnode_t *node, char *tail)
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync{
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync char *p;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync if (strcmp(tail, ".") == 0 || strcmp(tail, "..") == 0)
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync panic("construct path for %s", tail);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync p = kmem_alloc(strlen(node->sf_path) + 1 + strlen(tail) + 1, KM_SLEEP);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync strcpy(p, node->sf_path);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync strcat(p, "/");
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync strcat(p, tail);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync return (p);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync}
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
f48c3167a0f99da174686b66dc4e666f38ecae46vboxsync/*
f48c3167a0f99da174686b66dc4e666f38ecae46vboxsync * Clears the (cached) directory listing for the node.
f48c3167a0f99da174686b66dc4e666f38ecae46vboxsync */
f48c3167a0f99da174686b66dc4e666f38ecae46vboxsyncstatic void
f48c3167a0f99da174686b66dc4e666f38ecae46vboxsyncsfnode_clear_dir_list(sfnode_t *node)
f48c3167a0f99da174686b66dc4e666f38ecae46vboxsync{
f48c3167a0f99da174686b66dc4e666f38ecae46vboxsync ASSERT(MUTEX_HELD(&sffs_lock));
f48c3167a0f99da174686b66dc4e666f38ecae46vboxsync
f48c3167a0f99da174686b66dc4e666f38ecae46vboxsync while (node->sf_dir_list != NULL) {
f48c3167a0f99da174686b66dc4e666f38ecae46vboxsync sffs_dirents_t *next = node->sf_dir_list->sf_next;
f48c3167a0f99da174686b66dc4e666f38ecae46vboxsync kmem_free(node->sf_dir_list, SFFS_DIRENTS_SIZE);
f48c3167a0f99da174686b66dc4e666f38ecae46vboxsync node->sf_dir_list = next;
f48c3167a0f99da174686b66dc4e666f38ecae46vboxsync }
f48c3167a0f99da174686b66dc4e666f38ecae46vboxsync}
f48c3167a0f99da174686b66dc4e666f38ecae46vboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync/*
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync * Open the provider file associated with a vnode. Holding the file open is
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync * the only way we have of trying to have a vnode continue to refer to the
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync * same host file in the host in light of the possibility of host side renames.
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync */
1403063c7e0c0a072d59e323b66068b06278fb9avboxsyncstatic void
1076407eab87d42ab97c61074c7d9eacd143ef0fvboxsyncsfnode_open(sfnode_t *node, int flag)
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync{
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync int error;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync sfp_file_t *fp;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync if (node->sf_file != NULL)
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync return;
1076407eab87d42ab97c61074c7d9eacd143ef0fvboxsync error = sfprov_open(node->sf_sffs->sf_handle, node->sf_path, &fp, flag);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync if (error == 0)
1076407eab87d42ab97c61074c7d9eacd143ef0fvboxsync {
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync node->sf_file = fp;
1076407eab87d42ab97c61074c7d9eacd143ef0fvboxsync node->sf_flag = flag;
1076407eab87d42ab97c61074c7d9eacd143ef0fvboxsync }
1076407eab87d42ab97c61074c7d9eacd143ef0fvboxsync else
1076407eab87d42ab97c61074c7d9eacd143ef0fvboxsync node->sf_flag = ~0;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync}
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync/*
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync * get a new vnode reference for an sfnode
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync */
1403063c7e0c0a072d59e323b66068b06278fb9avboxsyncvnode_t *
1403063c7e0c0a072d59e323b66068b06278fb9avboxsyncsfnode_get_vnode(sfnode_t *node)
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync{
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync vnode_t *vp;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync if (node->sf_vnode != NULL) {
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync VN_HOLD(node->sf_vnode);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync } else {
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync vp = vn_alloc(KM_SLEEP);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync LogFlowFunc((" %s gets vnode 0x%p\n", node->sf_path, vp));
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync vp->v_type = node->sf_type;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync vp->v_vfsp = node->sf_sffs->sf_vfsp;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync vn_setops(vp, sffs_ops);
a2907076474e923411cc5046492a88787ba377fevboxsync vp->v_flag = VNOSWAP;
a2907076474e923411cc5046492a88787ba377fevboxsync#ifndef VBOXVFS_WITH_MMAP
a2907076474e923411cc5046492a88787ba377fevboxsync vp->v_flag |= VNOMAP;
a2907076474e923411cc5046492a88787ba377fevboxsync#endif
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync vn_exists(vp);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync vp->v_data = node;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync node->sf_vnode = vp;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync }
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync return (node->sf_vnode);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync}
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync/*
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync * Allocate and initialize a new sfnode and assign it a vnode
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync */
1403063c7e0c0a072d59e323b66068b06278fb9avboxsyncsfnode_t *
1403063c7e0c0a072d59e323b66068b06278fb9avboxsyncsfnode_make(
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync sffs_data_t *sffs,
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync char *path,
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync vtype_t type,
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync sfp_file_t *fp,
6479169ec893c18a646cec595e4e214492d180f0vboxsync sfnode_t *parent, /* can be NULL for root */
6479169ec893c18a646cec595e4e214492d180f0vboxsync sffs_stat_t *stat,
6479169ec893c18a646cec595e4e214492d180f0vboxsync uint64_t stat_time)
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync{
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync sfnode_t *node;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync avl_index_t where;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync ASSERT(MUTEX_HELD(&sffs_lock));
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync ASSERT(path != NULL);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync /*
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync * build the sfnode
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync */
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync LogFlowFunc(("sffs_make(%s)\n", path));
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync node = kmem_alloc(sizeof (*node), KM_SLEEP);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync node->sf_sffs = sffs;
ed39b7c986cc98221f3f2253f417f79f0f02c942vboxsync VFS_HOLD(node->sf_sffs->sf_vfsp);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync node->sf_path = path;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync node->sf_ino = sffs->sf_ino++;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync node->sf_type = type;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync node->sf_is_stale = 0; /* never stale at creation */
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync node->sf_file = fp;
1076407eab87d42ab97c61074c7d9eacd143ef0fvboxsync node->sf_flag = ~0;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync node->sf_vnode = NULL; /* do this before any sfnode_get_vnode() */
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync node->sf_children = 0;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync node->sf_parent = parent;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync if (parent)
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync ++parent->sf_children;
f48c3167a0f99da174686b66dc4e666f38ecae46vboxsync node->sf_dir_list = NULL;
6479169ec893c18a646cec595e4e214492d180f0vboxsync if (stat != NULL) {
6479169ec893c18a646cec595e4e214492d180f0vboxsync node->sf_stat = *stat;
6479169ec893c18a646cec595e4e214492d180f0vboxsync node->sf_stat_time = stat_time;
6479169ec893c18a646cec595e4e214492d180f0vboxsync } else {
6479169ec893c18a646cec595e4e214492d180f0vboxsync node->sf_stat_time = 0;
6479169ec893c18a646cec595e4e214492d180f0vboxsync }
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync /*
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync * add the new node to our cache
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync */
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync if (avl_find(&sfnodes, node, &where) != NULL)
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync panic("sffs_create_sfnode(%s): duplicate sfnode_t", path);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync avl_insert(&sfnodes, node, where);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync return (node);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync}
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync/*
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync * destroy an sfnode
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync */
1403063c7e0c0a072d59e323b66068b06278fb9avboxsyncstatic void
1403063c7e0c0a072d59e323b66068b06278fb9avboxsyncsfnode_destroy(sfnode_t *node)
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync{
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync avl_index_t where;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync avl_tree_t *tree;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync sfnode_t *parent;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsynctop:
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync parent = node->sf_parent;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync ASSERT(MUTEX_HELD(&sffs_lock));
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync ASSERT(node->sf_path != NULL);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync LogFlowFunc(("sffs_destroy(%s)%s\n", node->sf_path, node->sf_is_stale ? " stale": ""));
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync if (node->sf_children != 0)
35473cad6d5d5b57348c66f0cfdd7d51d6071ee7vboxsync panic("sfnode_destroy(%s) has %d children", node->sf_path, node->sf_children);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync if (node->sf_vnode != NULL)
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync panic("sfnode_destroy(%s) has active vnode", node->sf_path);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync if (node->sf_is_stale)
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync tree = &stale_sfnodes;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync else
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync tree = &sfnodes;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync if (avl_find(tree, node, &where) == NULL)
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync panic("sfnode_destroy(%s) not found", node->sf_path);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync avl_remove(tree, node);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync VFS_RELE(node->sf_sffs->sf_vfsp);
f48c3167a0f99da174686b66dc4e666f38ecae46vboxsync sfnode_clear_dir_list(node);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync kmem_free(node->sf_path, strlen(node->sf_path) + 1);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync kmem_free(node, sizeof (*node));
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync if (parent != NULL) {
f48c3167a0f99da174686b66dc4e666f38ecae46vboxsync sfnode_clear_dir_list(parent);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync if (parent->sf_children == 0)
16e6d031ca3d1ed4d88ae56fb94d9ad6e4d89c6bvboxsync panic("sfnode_destroy parent (%s) has no child", parent->sf_path);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync --parent->sf_children;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync if (parent->sf_children == 0 &&
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync parent->sf_is_stale &&
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync parent->sf_vnode == NULL) {
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync node = parent;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync goto top;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync }
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync }
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync}
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync/*
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync * Some sort of host operation on an sfnode has failed or it has been
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync * deleted. Mark this node and any children as stale, deleting knowledge
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync * about any which do not have active vnodes or children
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync * This also handle deleting an inactive node that was already stale.
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync */
1403063c7e0c0a072d59e323b66068b06278fb9avboxsyncstatic void
1403063c7e0c0a072d59e323b66068b06278fb9avboxsyncsfnode_make_stale(sfnode_t *node)
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync{
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync sfnode_t *n;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync int len;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync ASSERT(MUTEX_HELD(&sffs_lock));
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync avl_index_t where;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync /*
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync * First deal with any children of a directory node.
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync * If a directory becomes stale, anything below it becomes stale too.
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync */
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync if (!node->sf_is_stale && node->sf_type == VDIR) {
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync len = strlen(node->sf_path);
2084a447d1acb619df7c393fac41b79d517e4b3dvboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync n = node;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync while ((n = AVL_NEXT(&sfnodes, node)) != NULL) {
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync ASSERT(!n->sf_is_stale);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync /*
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync * quit when no longer seeing children of node
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync */
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync if (n->sf_sffs != node->sf_sffs ||
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync strncmp(node->sf_path, n->sf_path, len) != 0 ||
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync n->sf_path[len] != '/')
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync break;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync /*
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync * Either mark the child as stale or destroy it
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync */
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync if (n->sf_vnode == NULL && n->sf_children == 0) {
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync sfnode_destroy(n);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync } else {
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync LogFlowFunc(("sffs_make_stale(%s) sub\n", n->sf_path));
f48c3167a0f99da174686b66dc4e666f38ecae46vboxsync sfnode_clear_dir_list(n);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync if (avl_find(&sfnodes, n, &where) == NULL)
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync panic("sfnode_make_stale(%s)"
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync " not in sfnodes", n->sf_path);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync avl_remove(&sfnodes, n);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync n->sf_is_stale = 1;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync if (avl_find(&stale_sfnodes, n, &where) != NULL)
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync panic("sffs_make_stale(%s) duplicates",
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync n->sf_path);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync avl_insert(&stale_sfnodes, n, where);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync }
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync }
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync }
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync /*
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync * Now deal with the given node.
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync */
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync if (node->sf_vnode == NULL && node->sf_children == 0) {
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync sfnode_destroy(node);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync } else if (!node->sf_is_stale) {
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync LogFlowFunc(("sffs_make_stale(%s)\n", node->sf_path));
f48c3167a0f99da174686b66dc4e666f38ecae46vboxsync sfnode_clear_dir_list(node);
f48c3167a0f99da174686b66dc4e666f38ecae46vboxsync if (node->sf_parent)
f48c3167a0f99da174686b66dc4e666f38ecae46vboxsync sfnode_clear_dir_list(node->sf_parent);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync if (avl_find(&sfnodes, node, &where) == NULL)
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync panic("sfnode_make_stale(%s) not in sfnodes",
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync node->sf_path);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync avl_remove(&sfnodes, node);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync node->sf_is_stale = 1;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync if (avl_find(&stale_sfnodes, node, &where) != NULL)
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync panic("sffs_make_stale(%s) duplicates", node->sf_path);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync avl_insert(&stale_sfnodes, node, where);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync }
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync}
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
6479169ec893c18a646cec595e4e214492d180f0vboxsyncstatic uint64_t
6479169ec893c18a646cec595e4e214492d180f0vboxsyncsfnode_cur_time_usec(void)
6479169ec893c18a646cec595e4e214492d180f0vboxsync{
09e4ff0eddf453bdf8d622df2b48cff510f7d01dvboxsync clock_t now = drv_hztousec(ddi_get_lbolt());
09e4ff0eddf453bdf8d622df2b48cff510f7d01dvboxsync return now;
6479169ec893c18a646cec595e4e214492d180f0vboxsync}
6479169ec893c18a646cec595e4e214492d180f0vboxsync
6479169ec893c18a646cec595e4e214492d180f0vboxsyncstatic int
6479169ec893c18a646cec595e4e214492d180f0vboxsyncsfnode_stat_cached(sfnode_t *node)
6479169ec893c18a646cec595e4e214492d180f0vboxsync{
6479169ec893c18a646cec595e4e214492d180f0vboxsync return (sfnode_cur_time_usec() - node->sf_stat_time) <
6479169ec893c18a646cec595e4e214492d180f0vboxsync node->sf_sffs->sf_stat_ttl * 1000L;
6479169ec893c18a646cec595e4e214492d180f0vboxsync}
6479169ec893c18a646cec595e4e214492d180f0vboxsync
6479169ec893c18a646cec595e4e214492d180f0vboxsyncstatic void
6479169ec893c18a646cec595e4e214492d180f0vboxsyncsfnode_invalidate_stat_cache(sfnode_t *node)
6479169ec893c18a646cec595e4e214492d180f0vboxsync{
6479169ec893c18a646cec595e4e214492d180f0vboxsync node->sf_stat_time = 0;
6479169ec893c18a646cec595e4e214492d180f0vboxsync}
6479169ec893c18a646cec595e4e214492d180f0vboxsync
6479169ec893c18a646cec595e4e214492d180f0vboxsyncstatic int
6479169ec893c18a646cec595e4e214492d180f0vboxsyncsfnode_update_stat_cache(sfnode_t *node)
6479169ec893c18a646cec595e4e214492d180f0vboxsync{
6479169ec893c18a646cec595e4e214492d180f0vboxsync int error;
6479169ec893c18a646cec595e4e214492d180f0vboxsync
99eccc8f34de2d4b6af556ba2f5f0c756af237c7vboxsync error = sfprov_get_attr(node->sf_sffs->sf_handle, node->sf_path,
6479169ec893c18a646cec595e4e214492d180f0vboxsync &node->sf_stat);
6479169ec893c18a646cec595e4e214492d180f0vboxsync if (error == ENOENT)
6479169ec893c18a646cec595e4e214492d180f0vboxsync sfnode_make_stale(node);
6479169ec893c18a646cec595e4e214492d180f0vboxsync if (error == 0)
6479169ec893c18a646cec595e4e214492d180f0vboxsync node->sf_stat_time = sfnode_cur_time_usec();
6479169ec893c18a646cec595e4e214492d180f0vboxsync
6479169ec893c18a646cec595e4e214492d180f0vboxsync return (error);
6479169ec893c18a646cec595e4e214492d180f0vboxsync}
6479169ec893c18a646cec595e4e214492d180f0vboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync/*
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync * Rename a file or a directory
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync */
1403063c7e0c0a072d59e323b66068b06278fb9avboxsyncstatic void
1403063c7e0c0a072d59e323b66068b06278fb9avboxsyncsfnode_rename(sfnode_t *node, sfnode_t *newparent, char *path)
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync{
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync sfnode_t *n;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync sfnode_t template;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync avl_index_t where;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync int len = strlen(path);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync int old_len;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync char *new_path;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync char *tail;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync ASSERT(MUTEX_HELD(&sffs_lock));
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync ASSERT(!node->sf_is_stale);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync /*
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync * Have to remove anything existing that had the new name.
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync */
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync template.sf_sffs = node->sf_sffs;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync template.sf_path = path;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync template.sf_is_stale = 0;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync n = avl_find(&sfnodes, &template, &where);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync if (n != NULL)
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync sfnode_make_stale(n);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync /*
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync * Do the renaming, deal with any children of this node first.
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync */
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync if (node->sf_type == VDIR) {
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync old_len = strlen(node->sf_path);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync while ((n = AVL_NEXT(&sfnodes, node)) != NULL) {
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync /*
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync * quit when no longer seeing children of node
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync */
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync if (n->sf_sffs != node->sf_sffs ||
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync strncmp(node->sf_path, n->sf_path, old_len) != 0 ||
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync n->sf_path[old_len] != '/')
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync break;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync /*
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync * Rename the child:
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync * - build the new path name
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync * - unlink the AVL node
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync * - assign the new name
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync * - re-insert the AVL name
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync */
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync ASSERT(strlen(n->sf_path) > old_len);
ad27e1d5e48ca41245120c331cc88b50464813cevboxsync tail = n->sf_path + old_len; /* includes initial "/" */
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync new_path = kmem_alloc(len + strlen(tail) + 1,
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync KM_SLEEP);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync strcpy(new_path, path);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync strcat(new_path, tail);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync if (avl_find(&sfnodes, n, &where) == NULL)
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync panic("sfnode_rename(%s) not in sfnodes",
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync n->sf_path);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync avl_remove(&sfnodes, n);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync LogFlowFunc(("sfnode_rname(%s to %s) sub\n", n->sf_path, new_path));
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync kmem_free(n->sf_path, strlen(n->sf_path) + 1);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync n->sf_path = new_path;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync if (avl_find(&sfnodes, n, &where) != NULL)
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync panic("sfnode_rename(%s) duplicates",
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync n->sf_path);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync avl_insert(&sfnodes, n, where);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync }
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync }
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync /*
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync * Deal with the given node.
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync */
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync if (avl_find(&sfnodes, node, &where) == NULL)
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync panic("sfnode_rename(%s) not in sfnodes", node->sf_path);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync avl_remove(&sfnodes, node);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync LogFlowFunc(("sfnode_rname(%s to %s)\n", node->sf_path, path));
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync kmem_free(node->sf_path, strlen(node->sf_path) + 1);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync node->sf_path = path;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync if (avl_find(&sfnodes, node, &where) != NULL)
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync panic("sfnode_rename(%s) duplicates", node->sf_path);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync avl_insert(&sfnodes, node, where);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync /*
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync * change the parent
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync */
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync if (node->sf_parent == NULL)
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync panic("sfnode_rename(%s) no parent", node->sf_path);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync if (node->sf_parent->sf_children == 0)
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync panic("sfnode_rename(%s) parent has no child", node->sf_path);
f48c3167a0f99da174686b66dc4e666f38ecae46vboxsync sfnode_clear_dir_list(node->sf_parent);
f48c3167a0f99da174686b66dc4e666f38ecae46vboxsync sfnode_clear_dir_list(newparent);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync --node->sf_parent->sf_children;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync node->sf_parent = newparent;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync ++newparent->sf_children;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync}
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync/*
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync * Look for a cached node, if not found either handle ".." or try looking
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync * via the provider. Create an entry in sfnodes if found but not cached yet.
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync * If the create flag is set, a file or directory is created. If the file
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync * already existed, an error is returned.
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync * Nodes returned from this routine always have a vnode with its ref count
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync * bumped by 1.
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync */
1403063c7e0c0a072d59e323b66068b06278fb9avboxsyncstatic sfnode_t *
6479169ec893c18a646cec595e4e214492d180f0vboxsyncsfnode_lookup(
6479169ec893c18a646cec595e4e214492d180f0vboxsync sfnode_t *dir,
6479169ec893c18a646cec595e4e214492d180f0vboxsync char *name,
6479169ec893c18a646cec595e4e214492d180f0vboxsync vtype_t create,
e7bdfd4ea69601e5b2ddaf9a6794d3ab9f24e5e8vboxsync mode_t c_mode,
6479169ec893c18a646cec595e4e214492d180f0vboxsync sffs_stat_t *stat,
1519f0483877fddc0a03ab7e3382124f889bb36avboxsync uint64_t stat_time,
1519f0483877fddc0a03ab7e3382124f889bb36avboxsync int *err)
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync{
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync avl_index_t where;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync sfnode_t template;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync sfnode_t *node;
1519f0483877fddc0a03ab7e3382124f889bb36avboxsync int error = 0;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync int type;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync char *fullpath;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync sfp_file_t *fp;
6479169ec893c18a646cec595e4e214492d180f0vboxsync sffs_stat_t tmp_stat;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync ASSERT(MUTEX_HELD(&sffs_lock));
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1519f0483877fddc0a03ab7e3382124f889bb36avboxsync if (err)
1519f0483877fddc0a03ab7e3382124f889bb36avboxsync *err = error;
1519f0483877fddc0a03ab7e3382124f889bb36avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync /*
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync * handle referencing myself
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync */
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync if (strcmp(name, "") == 0 || strcmp(name, ".") == 0)
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync return (dir);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync /*
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync * deal with parent
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync */
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync if (strcmp(name, "..") == 0)
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync return (dir->sf_parent);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync /*
2084a447d1acb619df7c393fac41b79d517e4b3dvboxsync * Look for an existing node.
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync */
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync fullpath = sfnode_construct_path(dir, name);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync template.sf_sffs = dir->sf_sffs;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync template.sf_path = fullpath;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync template.sf_is_stale = 0;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync node = avl_find(&sfnodes, &template, &where);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync if (node != NULL) {
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync kmem_free(fullpath, strlen(fullpath) + 1);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync if (create != VNON)
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync return (NULL);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync return (node);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync }
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync /*
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync * No entry for this path currently.
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync * Check if the file exists with the provider and get the type from
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync * there.
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync */
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync if (create == VREG) {
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync type = VREG;
a50ca277f03cf9f8b4a8117a4950a85429d9ec0evboxsync stat = &tmp_stat;
e7bdfd4ea69601e5b2ddaf9a6794d3ab9f24e5e8vboxsync error = sfprov_create(dir->sf_sffs->sf_handle, fullpath, c_mode,
e7bdfd4ea69601e5b2ddaf9a6794d3ab9f24e5e8vboxsync &fp, stat);
e7bdfd4ea69601e5b2ddaf9a6794d3ab9f24e5e8vboxsync stat_time = sfnode_cur_time_usec();
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync } else if (create == VDIR) {
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync type = VDIR;
a50ca277f03cf9f8b4a8117a4950a85429d9ec0evboxsync stat = &tmp_stat;
e7bdfd4ea69601e5b2ddaf9a6794d3ab9f24e5e8vboxsync error = sfprov_mkdir(dir->sf_sffs->sf_handle, fullpath, c_mode,
e7bdfd4ea69601e5b2ddaf9a6794d3ab9f24e5e8vboxsync &fp, stat);
e7bdfd4ea69601e5b2ddaf9a6794d3ab9f24e5e8vboxsync stat_time = sfnode_cur_time_usec();
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync } else {
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync mode_t m;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync fp = NULL;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync type = VNON;
6479169ec893c18a646cec595e4e214492d180f0vboxsync if (stat == NULL) {
6479169ec893c18a646cec595e4e214492d180f0vboxsync stat = &tmp_stat;
99eccc8f34de2d4b6af556ba2f5f0c756af237c7vboxsync error = sfprov_get_attr(dir->sf_sffs->sf_handle,
6479169ec893c18a646cec595e4e214492d180f0vboxsync fullpath, stat);
6479169ec893c18a646cec595e4e214492d180f0vboxsync stat_time = sfnode_cur_time_usec();
6479169ec893c18a646cec595e4e214492d180f0vboxsync } else {
6479169ec893c18a646cec595e4e214492d180f0vboxsync error = 0;
6479169ec893c18a646cec595e4e214492d180f0vboxsync }
6479169ec893c18a646cec595e4e214492d180f0vboxsync m = stat->sf_mode;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync if (error != 0)
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync error = ENOENT;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync else if (S_ISDIR(m))
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync type = VDIR;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync else if (S_ISREG(m))
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync type = VREG;
99eccc8f34de2d4b6af556ba2f5f0c756af237c7vboxsync else if (S_ISLNK(m))
99eccc8f34de2d4b6af556ba2f5f0c756af237c7vboxsync type = VLNK;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync }
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1519f0483877fddc0a03ab7e3382124f889bb36avboxsync if (err)
1519f0483877fddc0a03ab7e3382124f889bb36avboxsync *err = error;
1519f0483877fddc0a03ab7e3382124f889bb36avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync /*
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync * If no errors, make a new node and return it.
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync */
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync if (error) {
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync kmem_free(fullpath, strlen(fullpath) + 1);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync return (NULL);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync }
6479169ec893c18a646cec595e4e214492d180f0vboxsync node = sfnode_make(dir->sf_sffs, fullpath, type, fp, dir, stat,
6479169ec893c18a646cec595e4e214492d180f0vboxsync stat_time);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync return (node);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync}
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync/*
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync * uid and gid in sffs determine owner and group for all files.
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync */
1403063c7e0c0a072d59e323b66068b06278fb9avboxsyncstatic int
1403063c7e0c0a072d59e323b66068b06278fb9avboxsyncsfnode_access(sfnode_t *node, mode_t mode, cred_t *cr)
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync{
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync sffs_data_t *sffs = node->sf_sffs;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync mode_t m;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync int shift = 0;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync int error;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync vnode_t *vp;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync ASSERT(MUTEX_HELD(&sffs_lock));
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync /*
6479169ec893c18a646cec595e4e214492d180f0vboxsync * get the mode from the cache or provider
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync */
6479169ec893c18a646cec595e4e214492d180f0vboxsync if (sfnode_stat_cached(node))
6479169ec893c18a646cec595e4e214492d180f0vboxsync error = 0;
6479169ec893c18a646cec595e4e214492d180f0vboxsync else
6479169ec893c18a646cec595e4e214492d180f0vboxsync error = sfnode_update_stat_cache(node);
96ccbd956a29c56d334c5031974eb88008373148vboxsync m = (error == 0) ? (node->sf_stat.sf_mode & MODEMASK) : 0;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync /*
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync * mask off the permissions based on uid/gid
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync */
96ccbd956a29c56d334c5031974eb88008373148vboxsync if (crgetuid(cr) != sffs->sf_handle->sf_uid) {
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync shift += 3;
96ccbd956a29c56d334c5031974eb88008373148vboxsync if (groupmember(sffs->sf_handle->sf_gid, cr) == 0)
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync shift += 3;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync }
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync mode &= ~(m << shift);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync if (mode == 0) {
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync error = 0;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync } else {
96ccbd956a29c56d334c5031974eb88008373148vboxsync /** @todo r=ramshankar: This can probably be optimized by holding static vnode
96ccbd956a29c56d334c5031974eb88008373148vboxsync * templates for dir/file, as it only checks the type rather than
96ccbd956a29c56d334c5031974eb88008373148vboxsync * fetching/allocating the real vnode. */
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync vp = sfnode_get_vnode(node);
96ccbd956a29c56d334c5031974eb88008373148vboxsync error = secpolicy_vnode_access(cr, vp, sffs->sf_handle->sf_uid, mode);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync VN_RELE(vp);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync }
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync return (error);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync}
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync/*
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync *
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync * Everything below this point are the vnode operations used by Solaris VFS
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync */
1403063c7e0c0a072d59e323b66068b06278fb9avboxsyncstatic int
1403063c7e0c0a072d59e323b66068b06278fb9avboxsyncsffs_readdir(
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync vnode_t *vp,
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync uio_t *uiop,
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync cred_t *cred,
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync int *eofp,
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync caller_context_t *ct,
1076407eab87d42ab97c61074c7d9eacd143ef0fvboxsync int flag)
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync{
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync sfnode_t *dir = VN2SFN(vp);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync sfnode_t *node;
72cc0d1a8b7c8406808a92eb0b9eb58bf6f8c3aavboxsync struct sffs_dirent *dirent = NULL;
f48c3167a0f99da174686b66dc4e666f38ecae46vboxsync sffs_dirents_t *cur_buf;
72cc0d1a8b7c8406808a92eb0b9eb58bf6f8c3aavboxsync offset_t offset = 0;
72cc0d1a8b7c8406808a92eb0b9eb58bf6f8c3aavboxsync offset_t orig_off = uiop->uio_loffset;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync int dummy_eof;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync int error = 0;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync if (uiop->uio_iovcnt != 1)
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync return (EINVAL);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync if (vp->v_type != VDIR)
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync return (ENOTDIR);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync if (eofp == NULL)
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync eofp = &dummy_eof;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync *eofp = 0;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
14a3a4c9d0c43ff4b0e32ee6e45e5c842527dc6dvboxsync if (uiop->uio_loffset >= MAXOFFSET_T) {
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync *eofp = 1;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync return (0);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync }
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync /*
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync * Get the directory entry names from the host. This gets all
f48c3167a0f99da174686b66dc4e666f38ecae46vboxsync * entries. These are stored in a linked list of sffs_dirents_t
f48c3167a0f99da174686b66dc4e666f38ecae46vboxsync * buffers, each of which contains a list of dirent64_t's.
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync */
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync mutex_enter(&sffs_lock);
f48c3167a0f99da174686b66dc4e666f38ecae46vboxsync
f48c3167a0f99da174686b66dc4e666f38ecae46vboxsync if (dir->sf_dir_list == NULL) {
f48c3167a0f99da174686b66dc4e666f38ecae46vboxsync error = sfprov_readdir(dir->sf_sffs->sf_handle, dir->sf_path,
1076407eab87d42ab97c61074c7d9eacd143ef0fvboxsync &dir->sf_dir_list, flag);
f48c3167a0f99da174686b66dc4e666f38ecae46vboxsync if (error != 0)
f48c3167a0f99da174686b66dc4e666f38ecae46vboxsync goto done;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync }
2084a447d1acb619df7c393fac41b79d517e4b3dvboxsync
72cc0d1a8b7c8406808a92eb0b9eb58bf6f8c3aavboxsync /*
72cc0d1a8b7c8406808a92eb0b9eb58bf6f8c3aavboxsync * Validate and skip to the desired offset.
72cc0d1a8b7c8406808a92eb0b9eb58bf6f8c3aavboxsync */
72cc0d1a8b7c8406808a92eb0b9eb58bf6f8c3aavboxsync cur_buf = dir->sf_dir_list;
72cc0d1a8b7c8406808a92eb0b9eb58bf6f8c3aavboxsync offset = 0;
72cc0d1a8b7c8406808a92eb0b9eb58bf6f8c3aavboxsync
72cc0d1a8b7c8406808a92eb0b9eb58bf6f8c3aavboxsync while (cur_buf != NULL &&
72cc0d1a8b7c8406808a92eb0b9eb58bf6f8c3aavboxsync offset + cur_buf->sf_len <= uiop->uio_loffset) {
72cc0d1a8b7c8406808a92eb0b9eb58bf6f8c3aavboxsync offset += cur_buf->sf_len;
72cc0d1a8b7c8406808a92eb0b9eb58bf6f8c3aavboxsync cur_buf = cur_buf->sf_next;
72cc0d1a8b7c8406808a92eb0b9eb58bf6f8c3aavboxsync }
72cc0d1a8b7c8406808a92eb0b9eb58bf6f8c3aavboxsync
72cc0d1a8b7c8406808a92eb0b9eb58bf6f8c3aavboxsync if (cur_buf == NULL && offset != uiop->uio_loffset) {
72cc0d1a8b7c8406808a92eb0b9eb58bf6f8c3aavboxsync error = EINVAL;
72cc0d1a8b7c8406808a92eb0b9eb58bf6f8c3aavboxsync goto done;
72cc0d1a8b7c8406808a92eb0b9eb58bf6f8c3aavboxsync }
72cc0d1a8b7c8406808a92eb0b9eb58bf6f8c3aavboxsync if (cur_buf != NULL && offset != uiop->uio_loffset) {
72cc0d1a8b7c8406808a92eb0b9eb58bf6f8c3aavboxsync offset_t off = offset;
72cc0d1a8b7c8406808a92eb0b9eb58bf6f8c3aavboxsync int step;
72cc0d1a8b7c8406808a92eb0b9eb58bf6f8c3aavboxsync dirent = &cur_buf->sf_entries[0];
72cc0d1a8b7c8406808a92eb0b9eb58bf6f8c3aavboxsync
72cc0d1a8b7c8406808a92eb0b9eb58bf6f8c3aavboxsync while (off < uiop->uio_loffset) {
72cc0d1a8b7c8406808a92eb0b9eb58bf6f8c3aavboxsync if (dirent->sf_entry.d_off == uiop->uio_loffset)
72cc0d1a8b7c8406808a92eb0b9eb58bf6f8c3aavboxsync break;
72cc0d1a8b7c8406808a92eb0b9eb58bf6f8c3aavboxsync step = sizeof(sffs_stat_t) + dirent->sf_entry.d_reclen;
72cc0d1a8b7c8406808a92eb0b9eb58bf6f8c3aavboxsync dirent = (struct sffs_dirent *) (((char *) dirent) + step);
72cc0d1a8b7c8406808a92eb0b9eb58bf6f8c3aavboxsync off += step;
72cc0d1a8b7c8406808a92eb0b9eb58bf6f8c3aavboxsync }
72cc0d1a8b7c8406808a92eb0b9eb58bf6f8c3aavboxsync
72cc0d1a8b7c8406808a92eb0b9eb58bf6f8c3aavboxsync if (off >= uiop->uio_loffset) {
72cc0d1a8b7c8406808a92eb0b9eb58bf6f8c3aavboxsync error = EINVAL;
72cc0d1a8b7c8406808a92eb0b9eb58bf6f8c3aavboxsync goto done;
72cc0d1a8b7c8406808a92eb0b9eb58bf6f8c3aavboxsync }
72cc0d1a8b7c8406808a92eb0b9eb58bf6f8c3aavboxsync }
72cc0d1a8b7c8406808a92eb0b9eb58bf6f8c3aavboxsync
72cc0d1a8b7c8406808a92eb0b9eb58bf6f8c3aavboxsync offset = uiop->uio_loffset - offset;
72cc0d1a8b7c8406808a92eb0b9eb58bf6f8c3aavboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync /*
f48c3167a0f99da174686b66dc4e666f38ecae46vboxsync * Lookup each of the names, so that we have ino's, and copy to
f48c3167a0f99da174686b66dc4e666f38ecae46vboxsync * result buffer.
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync */
f48c3167a0f99da174686b66dc4e666f38ecae46vboxsync while (cur_buf != NULL) {
72cc0d1a8b7c8406808a92eb0b9eb58bf6f8c3aavboxsync if (offset >= cur_buf->sf_len) {
f48c3167a0f99da174686b66dc4e666f38ecae46vboxsync cur_buf = cur_buf->sf_next;
72cc0d1a8b7c8406808a92eb0b9eb58bf6f8c3aavboxsync offset = 0;
f48c3167a0f99da174686b66dc4e666f38ecae46vboxsync continue;
f48c3167a0f99da174686b66dc4e666f38ecae46vboxsync }
f48c3167a0f99da174686b66dc4e666f38ecae46vboxsync
72cc0d1a8b7c8406808a92eb0b9eb58bf6f8c3aavboxsync dirent = (struct sffs_dirent *)
72cc0d1a8b7c8406808a92eb0b9eb58bf6f8c3aavboxsync (((char *) &cur_buf->sf_entries[0]) + offset);
72cc0d1a8b7c8406808a92eb0b9eb58bf6f8c3aavboxsync if (dirent->sf_entry.d_reclen > uiop->uio_resid)
f48c3167a0f99da174686b66dc4e666f38ecae46vboxsync break;
f48c3167a0f99da174686b66dc4e666f38ecae46vboxsync
72cc0d1a8b7c8406808a92eb0b9eb58bf6f8c3aavboxsync if (strcmp(dirent->sf_entry.d_name, ".") == 0) {
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync node = dir;
72cc0d1a8b7c8406808a92eb0b9eb58bf6f8c3aavboxsync } else if (strcmp(dirent->sf_entry.d_name, "..") == 0) {
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync node = dir->sf_parent;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync if (node == NULL)
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync node = dir;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync } else {
72cc0d1a8b7c8406808a92eb0b9eb58bf6f8c3aavboxsync node = sfnode_lookup(dir, dirent->sf_entry.d_name, VNON,
e7bdfd4ea69601e5b2ddaf9a6794d3ab9f24e5e8vboxsync 0, &dirent->sf_stat, sfnode_cur_time_usec(), NULL);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync if (node == NULL)
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync panic("sffs_readdir() lookup failed");
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync }
72cc0d1a8b7c8406808a92eb0b9eb58bf6f8c3aavboxsync dirent->sf_entry.d_ino = node->sf_ino;
f48c3167a0f99da174686b66dc4e666f38ecae46vboxsync
72cc0d1a8b7c8406808a92eb0b9eb58bf6f8c3aavboxsync error = uiomove(&dirent->sf_entry, dirent->sf_entry.d_reclen, UIO_READ, uiop);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync if (error != 0)
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync break;
72cc0d1a8b7c8406808a92eb0b9eb58bf6f8c3aavboxsync
72cc0d1a8b7c8406808a92eb0b9eb58bf6f8c3aavboxsync uiop->uio_loffset= dirent->sf_entry.d_off;
72cc0d1a8b7c8406808a92eb0b9eb58bf6f8c3aavboxsync offset += sizeof(sffs_stat_t) + dirent->sf_entry.d_reclen;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync }
f48c3167a0f99da174686b66dc4e666f38ecae46vboxsync if (error == 0 && cur_buf == NULL)
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync *eofp = 1;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsyncdone:
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync mutex_exit(&sffs_lock);
72cc0d1a8b7c8406808a92eb0b9eb58bf6f8c3aavboxsync if (error != 0)
72cc0d1a8b7c8406808a92eb0b9eb58bf6f8c3aavboxsync uiop->uio_loffset = orig_off;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync return (error);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync}
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync#if defined(VBOX_VFS_SOLARIS_10U6)
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync/*
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync * HERE JOE.. this may need more logic, need to look at other file systems
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync */
1403063c7e0c0a072d59e323b66068b06278fb9avboxsyncstatic int
1403063c7e0c0a072d59e323b66068b06278fb9avboxsyncsffs_pathconf(
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync vnode_t *vp,
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync int cmd,
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync ulong_t *valp,
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync cred_t *cr)
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync{
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync return (fs_pathconf(vp, cmd, valp, cr));
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync}
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync#else
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync/*
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync * HERE JOE.. this may need more logic, need to look at other file systems
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync */
1403063c7e0c0a072d59e323b66068b06278fb9avboxsyncstatic int
1403063c7e0c0a072d59e323b66068b06278fb9avboxsyncsffs_pathconf(
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync vnode_t *vp,
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync int cmd,
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync ulong_t *valp,
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync cred_t *cr,
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync caller_context_t *ct)
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync{
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync return (fs_pathconf(vp, cmd, valp, cr, ct));
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync}
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync#endif
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsyncstatic int
1403063c7e0c0a072d59e323b66068b06278fb9avboxsyncsffs_getattr(
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync vnode_t *vp,
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync vattr_t *vap,
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync int flags,
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync cred_t *cred,
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync caller_context_t *ct)
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync{
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync sfnode_t *node = VN2SFN(vp);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync sffs_data_t *sffs = node->sf_sffs;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync mode_t mode;
6479169ec893c18a646cec595e4e214492d180f0vboxsync int error = 0;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync mutex_enter(&sffs_lock);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync vap->va_type = vp->v_type;
96ccbd956a29c56d334c5031974eb88008373148vboxsync vap->va_uid = sffs->sf_handle->sf_uid;
96ccbd956a29c56d334c5031974eb88008373148vboxsync vap->va_gid = sffs->sf_handle->sf_gid;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync vap->va_fsid = sffs->sf_vfsp->vfs_dev;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync vap->va_nodeid = node->sf_ino;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync vap->va_nlink = 1;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync vap->va_rdev = sffs->sf_vfsp->vfs_dev;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync vap->va_seq = 0;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
6479169ec893c18a646cec595e4e214492d180f0vboxsync if (!sfnode_stat_cached(node)) {
6479169ec893c18a646cec595e4e214492d180f0vboxsync error = sfnode_update_stat_cache(node);
6479169ec893c18a646cec595e4e214492d180f0vboxsync if (error != 0)
6479169ec893c18a646cec595e4e214492d180f0vboxsync goto done;
6479169ec893c18a646cec595e4e214492d180f0vboxsync }
6479169ec893c18a646cec595e4e214492d180f0vboxsync
6479169ec893c18a646cec595e4e214492d180f0vboxsync vap->va_atime = node->sf_stat.sf_atime;
6479169ec893c18a646cec595e4e214492d180f0vboxsync vap->va_mtime = node->sf_stat.sf_mtime;
6479169ec893c18a646cec595e4e214492d180f0vboxsync vap->va_ctime = node->sf_stat.sf_ctime;
6479169ec893c18a646cec595e4e214492d180f0vboxsync
6479169ec893c18a646cec595e4e214492d180f0vboxsync mode = node->sf_stat.sf_mode;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync vap->va_mode = mode & MODEMASK;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
6479169ec893c18a646cec595e4e214492d180f0vboxsync vap->va_size = node->sf_stat.sf_size;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync vap->va_blksize = 512;
2703e64e42f9ce8800260f5112364cb6368711ffvboxsync vap->va_nblocks = (node->sf_stat.sf_alloc + 511) / 512;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsyncdone:
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync mutex_exit(&sffs_lock);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync return (error);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync}
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
f65dabff4474710524235022d328b737f174fc1dvboxsyncstatic int
f65dabff4474710524235022d328b737f174fc1dvboxsyncsffs_setattr(
f65dabff4474710524235022d328b737f174fc1dvboxsync vnode_t *vp,
f65dabff4474710524235022d328b737f174fc1dvboxsync vattr_t *vap,
f65dabff4474710524235022d328b737f174fc1dvboxsync int flags,
f65dabff4474710524235022d328b737f174fc1dvboxsync cred_t *cred,
f65dabff4474710524235022d328b737f174fc1dvboxsync caller_context_t *ct)
f65dabff4474710524235022d328b737f174fc1dvboxsync{
f65dabff4474710524235022d328b737f174fc1dvboxsync sfnode_t *node = VN2SFN(vp);
f65dabff4474710524235022d328b737f174fc1dvboxsync int error;
f65dabff4474710524235022d328b737f174fc1dvboxsync mode_t mode;
f65dabff4474710524235022d328b737f174fc1dvboxsync
f65dabff4474710524235022d328b737f174fc1dvboxsync mode = vap->va_mode;
f65dabff4474710524235022d328b737f174fc1dvboxsync if (vp->v_type == VREG)
f65dabff4474710524235022d328b737f174fc1dvboxsync mode |= S_IFREG;
f65dabff4474710524235022d328b737f174fc1dvboxsync else if (vp->v_type == VDIR)
f65dabff4474710524235022d328b737f174fc1dvboxsync mode |= S_IFDIR;
f65dabff4474710524235022d328b737f174fc1dvboxsync else if (vp->v_type == VBLK)
f65dabff4474710524235022d328b737f174fc1dvboxsync mode |= S_IFBLK;
f65dabff4474710524235022d328b737f174fc1dvboxsync else if (vp->v_type == VCHR)
f65dabff4474710524235022d328b737f174fc1dvboxsync mode |= S_IFCHR;
f65dabff4474710524235022d328b737f174fc1dvboxsync else if (vp->v_type == VLNK)
f65dabff4474710524235022d328b737f174fc1dvboxsync mode |= S_IFLNK;
f65dabff4474710524235022d328b737f174fc1dvboxsync else if (vp->v_type == VFIFO)
f65dabff4474710524235022d328b737f174fc1dvboxsync mode |= S_IFIFO;
f65dabff4474710524235022d328b737f174fc1dvboxsync else if (vp->v_type == VSOCK)
f65dabff4474710524235022d328b737f174fc1dvboxsync mode |= S_IFSOCK;
f65dabff4474710524235022d328b737f174fc1dvboxsync
f65dabff4474710524235022d328b737f174fc1dvboxsync mutex_enter(&sffs_lock);
f65dabff4474710524235022d328b737f174fc1dvboxsync
6479169ec893c18a646cec595e4e214492d180f0vboxsync sfnode_invalidate_stat_cache(node);
f65dabff4474710524235022d328b737f174fc1dvboxsync error = sfprov_set_attr(node->sf_sffs->sf_handle, node->sf_path,
f65dabff4474710524235022d328b737f174fc1dvboxsync vap->va_mask, mode, vap->va_atime, vap->va_mtime, vap->va_ctime);
f65dabff4474710524235022d328b737f174fc1dvboxsync if (error == ENOENT)
f65dabff4474710524235022d328b737f174fc1dvboxsync sfnode_make_stale(node);
f65dabff4474710524235022d328b737f174fc1dvboxsync
f65dabff4474710524235022d328b737f174fc1dvboxsync mutex_exit(&sffs_lock);
f65dabff4474710524235022d328b737f174fc1dvboxsync return (error);
f65dabff4474710524235022d328b737f174fc1dvboxsync}
f65dabff4474710524235022d328b737f174fc1dvboxsync
f65dabff4474710524235022d328b737f174fc1dvboxsyncstatic int
f65dabff4474710524235022d328b737f174fc1dvboxsyncsffs_space(
f65dabff4474710524235022d328b737f174fc1dvboxsync vnode_t *vp,
f65dabff4474710524235022d328b737f174fc1dvboxsync int cmd,
f65dabff4474710524235022d328b737f174fc1dvboxsync struct flock64 *bfp,
f65dabff4474710524235022d328b737f174fc1dvboxsync int flags,
f65dabff4474710524235022d328b737f174fc1dvboxsync offset_t off,
f65dabff4474710524235022d328b737f174fc1dvboxsync cred_t *cred,
f65dabff4474710524235022d328b737f174fc1dvboxsync caller_context_t *ct)
f65dabff4474710524235022d328b737f174fc1dvboxsync{
f65dabff4474710524235022d328b737f174fc1dvboxsync sfnode_t *node = VN2SFN(vp);
f65dabff4474710524235022d328b737f174fc1dvboxsync int error;
f65dabff4474710524235022d328b737f174fc1dvboxsync
f65dabff4474710524235022d328b737f174fc1dvboxsync /* we only support changing the length of the file */
f65dabff4474710524235022d328b737f174fc1dvboxsync if (bfp->l_whence != SEEK_SET || bfp->l_len != 0)
f65dabff4474710524235022d328b737f174fc1dvboxsync return ENOSYS;
f65dabff4474710524235022d328b737f174fc1dvboxsync
f65dabff4474710524235022d328b737f174fc1dvboxsync mutex_enter(&sffs_lock);
f65dabff4474710524235022d328b737f174fc1dvboxsync
6479169ec893c18a646cec595e4e214492d180f0vboxsync sfnode_invalidate_stat_cache(node);
6479169ec893c18a646cec595e4e214492d180f0vboxsync
f65dabff4474710524235022d328b737f174fc1dvboxsync error = sfprov_set_size(node->sf_sffs->sf_handle, node->sf_path,
f65dabff4474710524235022d328b737f174fc1dvboxsync bfp->l_start);
f65dabff4474710524235022d328b737f174fc1dvboxsync if (error == ENOENT)
f65dabff4474710524235022d328b737f174fc1dvboxsync sfnode_make_stale(node);
f65dabff4474710524235022d328b737f174fc1dvboxsync
f65dabff4474710524235022d328b737f174fc1dvboxsync mutex_exit(&sffs_lock);
f65dabff4474710524235022d328b737f174fc1dvboxsync return (error);
f65dabff4474710524235022d328b737f174fc1dvboxsync}
f65dabff4474710524235022d328b737f174fc1dvboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync/*ARGSUSED*/
1403063c7e0c0a072d59e323b66068b06278fb9avboxsyncstatic int
1403063c7e0c0a072d59e323b66068b06278fb9avboxsyncsffs_read(
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync vnode_t *vp,
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync struct uio *uio,
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync int ioflag,
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync cred_t *cred,
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync caller_context_t *ct)
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync{
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync sfnode_t *node = VN2SFN(vp);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync int error = 0;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync uint32_t bytes;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync uint32_t done;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync ulong_t offset;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync ssize_t total;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync if (vp->v_type == VDIR)
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync return (EISDIR);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync if (vp->v_type != VREG)
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync return (EINVAL);
14a3a4c9d0c43ff4b0e32ee6e45e5c842527dc6dvboxsync if (uio->uio_loffset >= MAXOFFSET_T)
14a3a4c9d0c43ff4b0e32ee6e45e5c842527dc6dvboxsync {
0c60d8c983faab959134e7652c16cd0c4ee5fbd6vboxsync /** @todo r=ramshankar: this is busted, kthread_t->t_procp has different
0c60d8c983faab959134e7652c16cd0c4ee5fbd6vboxsync * offsets between S10 and S11. Fix ASAP. */
2f4274a2244ba069210030c68f9ec618bed760e1vboxsync /* Raise psignal if the limit is exceeded. */
14a3a4c9d0c43ff4b0e32ee6e45e5c842527dc6dvboxsync proc_t *p = ttoproc(curthread);
14a3a4c9d0c43ff4b0e32ee6e45e5c842527dc6dvboxsync mutex_enter(&p->p_lock);
14a3a4c9d0c43ff4b0e32ee6e45e5c842527dc6dvboxsync (void) rctl_action(rctlproc_legacy[RLIMIT_FSIZE], p->p_rctls,
14a3a4c9d0c43ff4b0e32ee6e45e5c842527dc6dvboxsync p, RCA_UNSAFE_SIGINFO);
14a3a4c9d0c43ff4b0e32ee6e45e5c842527dc6dvboxsync mutex_exit(&p->p_lock);
14a3a4c9d0c43ff4b0e32ee6e45e5c842527dc6dvboxsync return (EFBIG);
14a3a4c9d0c43ff4b0e32ee6e45e5c842527dc6dvboxsync }
35473cad6d5d5b57348c66f0cfdd7d51d6071ee7vboxsync if (uio->uio_loffset < 0)
35473cad6d5d5b57348c66f0cfdd7d51d6071ee7vboxsync return (EINVAL);
35473cad6d5d5b57348c66f0cfdd7d51d6071ee7vboxsync total = uio->uio_resid;
35473cad6d5d5b57348c66f0cfdd7d51d6071ee7vboxsync if (total == 0)
35473cad6d5d5b57348c66f0cfdd7d51d6071ee7vboxsync return (0);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync mutex_enter(&sffs_lock);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync if (node->sf_file == NULL) {
1076407eab87d42ab97c61074c7d9eacd143ef0fvboxsync ASSERT(node->sf_flag != ~0);
1076407eab87d42ab97c61074c7d9eacd143ef0fvboxsync sfnode_open(node, node->sf_flag);
1076407eab87d42ab97c61074c7d9eacd143ef0fvboxsync if (node->sf_file == NULL)
1076407eab87d42ab97c61074c7d9eacd143ef0fvboxsync return (EBADF);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync }
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync do {
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync offset = uio->uio_offset;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync done = bytes = MIN(PAGESIZE, uio->uio_resid);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync error = sfprov_read(node->sf_file, sffs_buffer, offset, &done);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync if (error == 0 && done > 0)
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync error = uiomove(sffs_buffer, done, UIO_READ, uio);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync } while (error == 0 && uio->uio_resid > 0 && done > 0);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync mutex_exit(&sffs_lock);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync /*
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync * a partial read is never an error
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync */
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync if (total != uio->uio_resid)
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync error = 0;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync return (error);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync}
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync/*ARGSUSED*/
1403063c7e0c0a072d59e323b66068b06278fb9avboxsyncstatic int
1403063c7e0c0a072d59e323b66068b06278fb9avboxsyncsffs_write(
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync vnode_t *vp,
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync struct uio *uiop,
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync int ioflag,
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync cred_t *cred,
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync caller_context_t *ct)
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync{
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync sfnode_t *node = VN2SFN(vp);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync int error = 0;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync uint32_t bytes;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync uint32_t done;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync ulong_t offset;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync ssize_t total;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync rlim64_t limit = uiop->uio_llimit;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync if (vp->v_type == VDIR)
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync return (EISDIR);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync if (vp->v_type != VREG)
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync return (EINVAL);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync /*
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync * We have to hold this lock for a long time to keep
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync * multiple FAPPEND writes from intermixing
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync */
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync mutex_enter(&sffs_lock);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync if (node->sf_file == NULL) {
1076407eab87d42ab97c61074c7d9eacd143ef0fvboxsync ASSERT(node->sf_flag != ~0);
1076407eab87d42ab97c61074c7d9eacd143ef0fvboxsync sfnode_open(node, node->sf_flag);
1076407eab87d42ab97c61074c7d9eacd143ef0fvboxsync if (node->sf_file == NULL)
1076407eab87d42ab97c61074c7d9eacd143ef0fvboxsync return (EBADF);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync }
6479169ec893c18a646cec595e4e214492d180f0vboxsync
6479169ec893c18a646cec595e4e214492d180f0vboxsync sfnode_invalidate_stat_cache(node);
6479169ec893c18a646cec595e4e214492d180f0vboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync if (ioflag & FAPPEND) {
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync uint64_t endoffile;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync error = sfprov_get_size(node->sf_sffs->sf_handle,
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync node->sf_path, &endoffile);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync if (error == ENOENT)
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync sfnode_make_stale(node);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync if (error != 0) {
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync mutex_exit(&sffs_lock);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync return (error);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync }
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync uiop->uio_loffset = endoffile;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync }
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync if (vp->v_type != VREG || uiop->uio_loffset < 0) {
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync mutex_exit(&sffs_lock);
35473cad6d5d5b57348c66f0cfdd7d51d6071ee7vboxsync return (EINVAL);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync }
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync if (limit == RLIM64_INFINITY || limit > MAXOFFSET_T)
35473cad6d5d5b57348c66f0cfdd7d51d6071ee7vboxsync limit = MAXOFFSET_T;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync if (uiop->uio_loffset >= limit) {
0c60d8c983faab959134e7652c16cd0c4ee5fbd6vboxsync /** @todo r=ramshankar: this is busted, kthread_t->t_procp has different
0c60d8c983faab959134e7652c16cd0c4ee5fbd6vboxsync * offsets between S10 and S11. Fix ASAP. */
2f4274a2244ba069210030c68f9ec618bed760e1vboxsync /* Raise psignal if the limit is exceeded. */
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync proc_t *p = ttoproc(curthread);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync mutex_enter(&p->p_lock);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync (void) rctl_action(rctlproc_legacy[RLIMIT_FSIZE], p->p_rctls,
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync p, RCA_UNSAFE_SIGINFO);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync mutex_exit(&p->p_lock);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync mutex_exit(&sffs_lock);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync return (EFBIG);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync }
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
14a3a4c9d0c43ff4b0e32ee6e45e5c842527dc6dvboxsync if (uiop->uio_loffset >= MAXOFFSET_T) {
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync mutex_exit(&sffs_lock);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync return (EFBIG);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync }
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
35473cad6d5d5b57348c66f0cfdd7d51d6071ee7vboxsync total = uiop->uio_resid;
35473cad6d5d5b57348c66f0cfdd7d51d6071ee7vboxsync if (total == 0) {
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync mutex_exit(&sffs_lock);
35473cad6d5d5b57348c66f0cfdd7d51d6071ee7vboxsync return (0);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync }
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync do {
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync offset = uiop->uio_offset;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync bytes = MIN(PAGESIZE, uiop->uio_resid);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync if (offset + bytes >= limit) {
35473cad6d5d5b57348c66f0cfdd7d51d6071ee7vboxsync if (offset >= limit) {
35473cad6d5d5b57348c66f0cfdd7d51d6071ee7vboxsync error = EFBIG;
35473cad6d5d5b57348c66f0cfdd7d51d6071ee7vboxsync break;
35473cad6d5d5b57348c66f0cfdd7d51d6071ee7vboxsync }
35473cad6d5d5b57348c66f0cfdd7d51d6071ee7vboxsync bytes = limit - offset;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync }
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync error = uiomove(sffs_buffer, bytes, UIO_WRITE, uiop);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync if (error != 0)
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync break;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync done = bytes;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync if (error == 0)
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync error = sfprov_write(node->sf_file, sffs_buffer,
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync offset, &done);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync total -= done;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync if (done != bytes) {
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync uiop->uio_resid += bytes - done;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync break;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync }
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync } while (error == 0 && uiop->uio_resid > 0 && done > 0);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync mutex_exit(&sffs_lock);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync /*
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync * A short write is never really an error.
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync */
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync if (total != uiop->uio_resid)
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync error = 0;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync return (error);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync}
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync/*ARGSUSED*/
1403063c7e0c0a072d59e323b66068b06278fb9avboxsyncstatic int
1403063c7e0c0a072d59e323b66068b06278fb9avboxsyncsffs_access(vnode_t *vp, int mode, int flags, cred_t *cr, caller_context_t *ct)
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync{
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync sfnode_t *node = VN2SFN(vp);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync int error;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync mutex_enter(&sffs_lock);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync error = sfnode_access(node, mode, cr);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync mutex_exit(&sffs_lock);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync return (error);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync}
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync/*
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync * Lookup an entry in a directory and create a new vnode if found.
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync */
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync/* ARGSUSED3 */
1403063c7e0c0a072d59e323b66068b06278fb9avboxsyncstatic int
1403063c7e0c0a072d59e323b66068b06278fb9avboxsyncsffs_lookup(
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync vnode_t *dvp, /* the directory vnode */
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync char *name, /* the name of the file or directory */
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync vnode_t **vpp, /* the vnode we found or NULL */
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync struct pathname *pnp,
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync int flags,
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync vnode_t *rdir,
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync cred_t *cred,
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync caller_context_t *ct,
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync int *direntflags,
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync struct pathname *realpnp)
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync{
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync int error;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync sfnode_t *node;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync /*
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync * dvp must be a directory
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync */
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync if (dvp->v_type != VDIR)
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync return (ENOTDIR);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync /*
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync * An empty component name or just "." means the directory itself.
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync * Don't do any further lookup or checking.
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync */
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync if (strcmp(name, "") == 0 || strcmp(name, ".") == 0) {
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync VN_HOLD(dvp);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync *vpp = dvp;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync return (0);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync }
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync /*
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync * Check permission to look at this directory. We always allow "..".
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync */
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync mutex_enter(&sffs_lock);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync if (strcmp(name, "..") != 0) {
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync error = sfnode_access(VN2SFN(dvp), VEXEC, cred);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync if (error) {
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync mutex_exit(&sffs_lock);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync return (error);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync }
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync }
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync /*
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync * Lookup the node.
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync */
e7bdfd4ea69601e5b2ddaf9a6794d3ab9f24e5e8vboxsync node = sfnode_lookup(VN2SFN(dvp), name, VNON, 0, NULL, 0, NULL);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync if (node != NULL)
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync *vpp = sfnode_get_vnode(node);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync mutex_exit(&sffs_lock);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync return ((node == NULL) ? ENOENT : 0);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync}
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync/*ARGSUSED*/
1403063c7e0c0a072d59e323b66068b06278fb9avboxsyncstatic int
1403063c7e0c0a072d59e323b66068b06278fb9avboxsyncsffs_create(
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync vnode_t *dvp,
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync char *name,
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync struct vattr *vap,
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync vcexcl_t exclusive,
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync int mode,
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync vnode_t **vpp,
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync cred_t *cr,
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync int flag,
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync caller_context_t *ct,
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync vsecattr_t *vsecp)
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync{
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync vnode_t *vp;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync sfnode_t *node;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync int error;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync ASSERT(name != NULL);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync /*
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync * this is used for regular files, not mkdir
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync */
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync if (vap->va_type == VDIR)
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync return (EISDIR);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync if (vap->va_type != VREG)
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync return (EINVAL);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync /*
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync * is this a pre-existing file?
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync */
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync error = sffs_lookup(dvp, name, &vp,
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync NULL, 0, NULL, cr, ct, NULL, NULL);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync if (error == ENOENT)
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync vp = NULL;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync else if (error != 0)
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync return (error);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync /*
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync * Operation on a pre-existing file.
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync */
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync if (vp != NULL) {
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync if (exclusive == EXCL) {
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync VN_RELE(vp);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync return (EEXIST);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync }
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync if (vp->v_type == VDIR && (mode & VWRITE) == VWRITE) {
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync VN_RELE(vp);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync return (EISDIR);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync }
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync mutex_enter(&sffs_lock);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync node = VN2SFN(vp);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync error = sfnode_access(node, mode, cr);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync if (error != 0) {
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync mutex_exit(&sffs_lock);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync VN_RELE(vp);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync return (error);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync }
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
6479169ec893c18a646cec595e4e214492d180f0vboxsync sfnode_invalidate_stat_cache(VN2SFN(dvp));
6479169ec893c18a646cec595e4e214492d180f0vboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync /*
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync * handle truncating an existing file
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync */
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync if (vp->v_type == VREG && (vap->va_mask & AT_SIZE) &&
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync vap->va_size == 0) {
1076407eab87d42ab97c61074c7d9eacd143ef0fvboxsync sfnode_open(node, flag | FTRUNC);
1076407eab87d42ab97c61074c7d9eacd143ef0fvboxsync if (node->sf_path == NULL) {
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync mutex_exit(&sffs_lock);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync VN_RELE(vp);
1076407eab87d42ab97c61074c7d9eacd143ef0fvboxsync return (ENOENT);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync }
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync }
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync mutex_exit(&sffs_lock);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync *vpp = vp;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync return (0);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync }
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync /*
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync * Create a new node. First check for a race creating it.
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync */
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync mutex_enter(&sffs_lock);
e7bdfd4ea69601e5b2ddaf9a6794d3ab9f24e5e8vboxsync node = sfnode_lookup(VN2SFN(dvp), name, VNON, 0, NULL, 0, NULL);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync if (node != NULL) {
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync mutex_exit(&sffs_lock);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync return (EEXIST);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync }
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync /*
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync * Doesn't exist yet and we have the lock, so create it.
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync */
6479169ec893c18a646cec595e4e214492d180f0vboxsync sfnode_invalidate_stat_cache(VN2SFN(dvp));
1519f0483877fddc0a03ab7e3382124f889bb36avboxsync int lookuperr;
e7bdfd4ea69601e5b2ddaf9a6794d3ab9f24e5e8vboxsync node = sfnode_lookup(VN2SFN(dvp), name, VREG,
e7bdfd4ea69601e5b2ddaf9a6794d3ab9f24e5e8vboxsync (vap->va_mask & AT_MODE) ? vap->va_mode : 0, NULL, 0, &lookuperr);
6e89506dd9d878449c4850f0ef4ade3424e2f1c1vboxsync
91ec4b43ffbf2a38ec79abe529bf141f7f7d4e93vboxsync if (node && node->sf_parent)
f48c3167a0f99da174686b66dc4e666f38ecae46vboxsync sfnode_clear_dir_list(node->sf_parent);
f48c3167a0f99da174686b66dc4e666f38ecae46vboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync mutex_exit(&sffs_lock);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync if (node == NULL)
1519f0483877fddc0a03ab7e3382124f889bb36avboxsync return (lookuperr);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync *vpp = sfnode_get_vnode(node);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync return (0);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync}
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync/*ARGSUSED*/
1403063c7e0c0a072d59e323b66068b06278fb9avboxsyncstatic int
1403063c7e0c0a072d59e323b66068b06278fb9avboxsyncsffs_mkdir(
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync vnode_t *dvp,
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync char *nm,
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync vattr_t *va,
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync vnode_t **vpp,
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync cred_t *cred,
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync caller_context_t *ct,
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync int flags,
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync vsecattr_t *vsecp)
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync{
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync sfnode_t *node;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync vnode_t *vp;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync int error;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync /*
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync * These should never happen
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync */
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync ASSERT(nm != NULL);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync ASSERT(strcmp(nm, "") != 0);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync ASSERT(strcmp(nm, ".") != 0);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync ASSERT(strcmp(nm, "..") != 0);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync /*
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync * Do an unlocked look up first
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync */
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync error = sffs_lookup(dvp, nm, &vp, NULL, 0, NULL, cred, ct, NULL, NULL);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync if (error == 0) {
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync VN_RELE(vp);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync return (EEXIST);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync }
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync if (error != ENOENT)
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync return (error);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync /*
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync * Must be able to write in current directory
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync */
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync mutex_enter(&sffs_lock);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync error = sfnode_access(VN2SFN(dvp), VWRITE, cred);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync if (error) {
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync mutex_exit(&sffs_lock);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync return (error);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync }
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
6479169ec893c18a646cec595e4e214492d180f0vboxsync sfnode_invalidate_stat_cache(VN2SFN(dvp));
1519f0483877fddc0a03ab7e3382124f889bb36avboxsync int lookuperr = EACCES;
e7bdfd4ea69601e5b2ddaf9a6794d3ab9f24e5e8vboxsync node = sfnode_lookup(VN2SFN(dvp), nm, VDIR,
e7bdfd4ea69601e5b2ddaf9a6794d3ab9f24e5e8vboxsync (va->va_mode & AT_MODE) ? va->va_mode : 0, NULL, 0, &lookuperr);
6e89506dd9d878449c4850f0ef4ade3424e2f1c1vboxsync
1519f0483877fddc0a03ab7e3382124f889bb36avboxsync if (node && node->sf_parent)
f48c3167a0f99da174686b66dc4e666f38ecae46vboxsync sfnode_clear_dir_list(node->sf_parent);
f48c3167a0f99da174686b66dc4e666f38ecae46vboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync mutex_exit(&sffs_lock);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync if (node == NULL)
1519f0483877fddc0a03ab7e3382124f889bb36avboxsync return (lookuperr);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync *vpp = sfnode_get_vnode(node);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync return (0);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync}
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync/*ARGSUSED*/
1403063c7e0c0a072d59e323b66068b06278fb9avboxsyncstatic int
1403063c7e0c0a072d59e323b66068b06278fb9avboxsyncsffs_rmdir(
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync struct vnode *dvp,
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync char *nm,
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync vnode_t *cdir,
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync cred_t *cred,
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync caller_context_t *ct,
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync int flags)
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync{
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync sfnode_t *node;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync vnode_t *vp;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync int error;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync /*
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync * Return error when removing . and ..
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync */
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync if (strcmp(nm, ".") == 0 || strcmp(nm, "") == 0)
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync return (EINVAL);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync if (strcmp(nm, "..") == 0)
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync return (EEXIST);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync error = sffs_lookup(dvp, nm, &vp, NULL, 0, NULL, cred, ct, NULL, NULL);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync if (error)
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync return (error);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync if (vp->v_type != VDIR) {
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync VN_RELE(vp);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync return (ENOTDIR);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync }
09ca25a8a278cde483cba79172249b42179d796fvboxsync
a2907076474e923411cc5046492a88787ba377fevboxsync#ifdef VBOXVFS_WITH_MMAP
09ca25a8a278cde483cba79172249b42179d796fvboxsync if (vn_vfswlock(vp)) {
09ca25a8a278cde483cba79172249b42179d796fvboxsync VN_RELE(vp);
09ca25a8a278cde483cba79172249b42179d796fvboxsync return (EBUSY);
09ca25a8a278cde483cba79172249b42179d796fvboxsync }
09ca25a8a278cde483cba79172249b42179d796fvboxsync#endif
09ca25a8a278cde483cba79172249b42179d796fvboxsync
09ca25a8a278cde483cba79172249b42179d796fvboxsync if (vn_mountedvfs(vp)) {
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync VN_RELE(vp);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync return (EBUSY);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync }
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync node = VN2SFN(vp);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync mutex_enter(&sffs_lock);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync error = sfnode_access(VN2SFN(dvp), VEXEC | VWRITE, cred);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync if (error)
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync goto done;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync /*
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync * If anything else is using this vnode, then fail the remove.
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync * Why? Windows hosts can't remove something that is open,
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync * so we have to sfprov_close() it first.
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync * There is no errno for this - since it's not a problem on UNIX,
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync * but EINVAL is the closest.
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync */
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync if (node->sf_file != NULL) {
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync if (vp->v_count > 1) {
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync error = EINVAL;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync goto done;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync }
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync (void)sfprov_close(node->sf_file);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync node->sf_file = NULL;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync }
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync /*
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync * Remove the directory on the host and mark the node as stale.
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync */
6479169ec893c18a646cec595e4e214492d180f0vboxsync sfnode_invalidate_stat_cache(VN2SFN(dvp));
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync error = sfprov_rmdir(node->sf_sffs->sf_handle, node->sf_path);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync if (error == ENOENT || error == 0)
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync sfnode_make_stale(node);
f48c3167a0f99da174686b66dc4e666f38ecae46vboxsync
f48c3167a0f99da174686b66dc4e666f38ecae46vboxsync if (node->sf_parent)
f48c3167a0f99da174686b66dc4e666f38ecae46vboxsync sfnode_clear_dir_list(node->sf_parent);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsyncdone:
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync mutex_exit(&sffs_lock);
a1d98beb9dd67c242ecb725dc6df3c5e390524b0vboxsync#ifdef VBOXVFS_WITH_MMAP
a1d98beb9dd67c242ecb725dc6df3c5e390524b0vboxsync vn_vfsunlock(vp);
a1d98beb9dd67c242ecb725dc6df3c5e390524b0vboxsync#endif
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync VN_RELE(vp);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync return (error);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync}
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
a2907076474e923411cc5046492a88787ba377fevboxsync#ifdef VBOXVFS_WITH_MMAP
fb4eaa62a6bbeb82a89703d833d39339783feb4avboxsyncstatic caddr_t
fb4eaa62a6bbeb82a89703d833d39339783feb4avboxsyncsffs_page_map(
fb4eaa62a6bbeb82a89703d833d39339783feb4avboxsync page_t *ppage,
fb4eaa62a6bbeb82a89703d833d39339783feb4avboxsync enum seg_rw segaccess)
fb4eaa62a6bbeb82a89703d833d39339783feb4avboxsync{
fb4eaa62a6bbeb82a89703d833d39339783feb4avboxsync /* Use seg_kpm driver if possible (64-bit) */
fb4eaa62a6bbeb82a89703d833d39339783feb4avboxsync if (kpm_enable)
fb4eaa62a6bbeb82a89703d833d39339783feb4avboxsync return (hat_kpm_mapin(ppage, NULL));
fb4eaa62a6bbeb82a89703d833d39339783feb4avboxsync ASSERT(segaccess == S_READ || segaccess == S_WRITE);
fb4eaa62a6bbeb82a89703d833d39339783feb4avboxsync return (ppmapin(ppage, PROT_READ | ((segaccess == S_WRITE) ? PROT_WRITE : 0), (caddr_t)-1));
fb4eaa62a6bbeb82a89703d833d39339783feb4avboxsync}
fb4eaa62a6bbeb82a89703d833d39339783feb4avboxsync
fb4eaa62a6bbeb82a89703d833d39339783feb4avboxsync
fb4eaa62a6bbeb82a89703d833d39339783feb4avboxsyncstatic void
fb4eaa62a6bbeb82a89703d833d39339783feb4avboxsyncsffs_page_unmap(
fb4eaa62a6bbeb82a89703d833d39339783feb4avboxsync page_t *ppage,
fb4eaa62a6bbeb82a89703d833d39339783feb4avboxsync caddr_t addr)
fb4eaa62a6bbeb82a89703d833d39339783feb4avboxsync{
fb4eaa62a6bbeb82a89703d833d39339783feb4avboxsync if (kpm_enable)
fb4eaa62a6bbeb82a89703d833d39339783feb4avboxsync hat_kpm_mapout(ppage, NULL, addr);
fb4eaa62a6bbeb82a89703d833d39339783feb4avboxsync else
fb4eaa62a6bbeb82a89703d833d39339783feb4avboxsync ppmapout(addr);
fb4eaa62a6bbeb82a89703d833d39339783feb4avboxsync}
fb4eaa62a6bbeb82a89703d833d39339783feb4avboxsync
fb4eaa62a6bbeb82a89703d833d39339783feb4avboxsync
fb4eaa62a6bbeb82a89703d833d39339783feb4avboxsync/*
fb4eaa62a6bbeb82a89703d833d39339783feb4avboxsync * Called when there's no page in the cache. This will create new page(s) and read
fb4eaa62a6bbeb82a89703d833d39339783feb4avboxsync * the file data into it.
fb4eaa62a6bbeb82a89703d833d39339783feb4avboxsync */
a2907076474e923411cc5046492a88787ba377fevboxsyncstatic int
fb4eaa62a6bbeb82a89703d833d39339783feb4avboxsyncsffs_readpages(
fb4eaa62a6bbeb82a89703d833d39339783feb4avboxsync vnode_t *dvp,
fb4eaa62a6bbeb82a89703d833d39339783feb4avboxsync offset_t off,
fb4eaa62a6bbeb82a89703d833d39339783feb4avboxsync page_t *pagelist[],
fb4eaa62a6bbeb82a89703d833d39339783feb4avboxsync size_t pagelistsize,
fb4eaa62a6bbeb82a89703d833d39339783feb4avboxsync struct seg *segp,
fb4eaa62a6bbeb82a89703d833d39339783feb4avboxsync caddr_t addr,
fb4eaa62a6bbeb82a89703d833d39339783feb4avboxsync enum seg_rw segaccess)
fb4eaa62a6bbeb82a89703d833d39339783feb4avboxsync{
fb4eaa62a6bbeb82a89703d833d39339783feb4avboxsync ASSERT(MUTEX_HELD(&sffs_lock));
fb4eaa62a6bbeb82a89703d833d39339783feb4avboxsync
fb4eaa62a6bbeb82a89703d833d39339783feb4avboxsync int error = 0;
fb4eaa62a6bbeb82a89703d833d39339783feb4avboxsync u_offset_t io_off, total;
fb4eaa62a6bbeb82a89703d833d39339783feb4avboxsync size_t io_len;
fb4eaa62a6bbeb82a89703d833d39339783feb4avboxsync page_t *ppages;
fb4eaa62a6bbeb82a89703d833d39339783feb4avboxsync page_t *pcur;
fb4eaa62a6bbeb82a89703d833d39339783feb4avboxsync
fb4eaa62a6bbeb82a89703d833d39339783feb4avboxsync sfnode_t *node = VN2SFN(dvp);
fb4eaa62a6bbeb82a89703d833d39339783feb4avboxsync ASSERT(node);
fb4eaa62a6bbeb82a89703d833d39339783feb4avboxsync ASSERT(node->sf_file);
fb4eaa62a6bbeb82a89703d833d39339783feb4avboxsync
fb4eaa62a6bbeb82a89703d833d39339783feb4avboxsync if (pagelistsize == PAGESIZE)
fb4eaa62a6bbeb82a89703d833d39339783feb4avboxsync {
fb4eaa62a6bbeb82a89703d833d39339783feb4avboxsync io_off = off;
fb4eaa62a6bbeb82a89703d833d39339783feb4avboxsync io_len = PAGESIZE;
fb4eaa62a6bbeb82a89703d833d39339783feb4avboxsync ppages = page_create_va(dvp, io_off, io_len, PG_WAIT | PG_EXCL, segp, addr);
fb4eaa62a6bbeb82a89703d833d39339783feb4avboxsync }
fb4eaa62a6bbeb82a89703d833d39339783feb4avboxsync else
fb4eaa62a6bbeb82a89703d833d39339783feb4avboxsync ppages = pvn_read_kluster(dvp, off, segp, addr, &io_off, &io_len, off, pagelistsize, 0);
fb4eaa62a6bbeb82a89703d833d39339783feb4avboxsync
fb4eaa62a6bbeb82a89703d833d39339783feb4avboxsync /* If page already exists return success */
fb4eaa62a6bbeb82a89703d833d39339783feb4avboxsync if (!ppages)
fb4eaa62a6bbeb82a89703d833d39339783feb4avboxsync {
fb4eaa62a6bbeb82a89703d833d39339783feb4avboxsync *pagelist = NULL;
fb4eaa62a6bbeb82a89703d833d39339783feb4avboxsync return (0);
fb4eaa62a6bbeb82a89703d833d39339783feb4avboxsync }
fb4eaa62a6bbeb82a89703d833d39339783feb4avboxsync
fb4eaa62a6bbeb82a89703d833d39339783feb4avboxsync /*
fb4eaa62a6bbeb82a89703d833d39339783feb4avboxsync * Map & read page-by-page.
fb4eaa62a6bbeb82a89703d833d39339783feb4avboxsync */
fb4eaa62a6bbeb82a89703d833d39339783feb4avboxsync total = io_off + io_len;
fb4eaa62a6bbeb82a89703d833d39339783feb4avboxsync pcur = ppages;
fb4eaa62a6bbeb82a89703d833d39339783feb4avboxsync while (io_off < total)
fb4eaa62a6bbeb82a89703d833d39339783feb4avboxsync {
fb4eaa62a6bbeb82a89703d833d39339783feb4avboxsync ASSERT3U(io_off, ==, pcur->p_offset);
fb4eaa62a6bbeb82a89703d833d39339783feb4avboxsync
fb4eaa62a6bbeb82a89703d833d39339783feb4avboxsync caddr_t virtaddr = sffs_page_map(pcur, segaccess);
fb4eaa62a6bbeb82a89703d833d39339783feb4avboxsync uint32_t bytes = PAGESIZE;
fb4eaa62a6bbeb82a89703d833d39339783feb4avboxsync error = sfprov_read(node->sf_file, virtaddr, io_off, &bytes);
7aa325a10935ed82649b38021832545e9af807b7vboxsync /*
7aa325a10935ed82649b38021832545e9af807b7vboxsync * If we reuse pages without zero'ing them, one process can mmap() and read-past the length
7aa325a10935ed82649b38021832545e9af807b7vboxsync * to read previously mmap'd contents (from possibly other processes).
7aa325a10935ed82649b38021832545e9af807b7vboxsync */
7aa325a10935ed82649b38021832545e9af807b7vboxsync if (error == 0 && bytes < PAGESIZE)
7aa325a10935ed82649b38021832545e9af807b7vboxsync memset(virtaddr + bytes, 0, PAGESIZE - bytes);
fb4eaa62a6bbeb82a89703d833d39339783feb4avboxsync sffs_page_unmap(pcur, virtaddr);
a2907076474e923411cc5046492a88787ba377fevboxsync if (error != 0)
fb4eaa62a6bbeb82a89703d833d39339783feb4avboxsync {
ebbe78c52653f516133cf68ac0199b35c1d96ddfvboxsync cmn_err(CE_WARN, "sffs_readpages: sfprov_read() failed. error=%d bytes=%u\n", error, bytes);
fb4eaa62a6bbeb82a89703d833d39339783feb4avboxsync /* Get rid of all kluster pages read & bail. */
ebbe78c52653f516133cf68ac0199b35c1d96ddfvboxsync pvn_read_done(ppages, B_ERROR);
fb4eaa62a6bbeb82a89703d833d39339783feb4avboxsync return (error);
fb4eaa62a6bbeb82a89703d833d39339783feb4avboxsync }
fb4eaa62a6bbeb82a89703d833d39339783feb4avboxsync pcur = pcur->p_next;
fb4eaa62a6bbeb82a89703d833d39339783feb4avboxsync io_off += PAGESIZE;
fb4eaa62a6bbeb82a89703d833d39339783feb4avboxsync }
fb4eaa62a6bbeb82a89703d833d39339783feb4avboxsync
fb4eaa62a6bbeb82a89703d833d39339783feb4avboxsync /*
fb4eaa62a6bbeb82a89703d833d39339783feb4avboxsync * Fill in the pagelist from kluster at the requested offset.
fb4eaa62a6bbeb82a89703d833d39339783feb4avboxsync */
fb4eaa62a6bbeb82a89703d833d39339783feb4avboxsync pvn_plist_init(ppages, pagelist, pagelistsize, off, io_len, segaccess);
fb4eaa62a6bbeb82a89703d833d39339783feb4avboxsync ASSERT(pagelist == NULL || (*pagelist)->p_offset == off);
fb4eaa62a6bbeb82a89703d833d39339783feb4avboxsync return (0);
fb4eaa62a6bbeb82a89703d833d39339783feb4avboxsync}
fb4eaa62a6bbeb82a89703d833d39339783feb4avboxsync
fb4eaa62a6bbeb82a89703d833d39339783feb4avboxsync
561b8d2b46fb10887829b7e4d7d29447817adbddvboxsync/*ARGSUSED*/
561b8d2b46fb10887829b7e4d7d29447817adbddvboxsyncstatic int
561b8d2b46fb10887829b7e4d7d29447817adbddvboxsyncsffs_getpage(
561b8d2b46fb10887829b7e4d7d29447817adbddvboxsync vnode_t *dvp,
561b8d2b46fb10887829b7e4d7d29447817adbddvboxsync offset_t off,
561b8d2b46fb10887829b7e4d7d29447817adbddvboxsync size_t len,
561b8d2b46fb10887829b7e4d7d29447817adbddvboxsync uint_t *protp,
561b8d2b46fb10887829b7e4d7d29447817adbddvboxsync page_t *pagelist[],
561b8d2b46fb10887829b7e4d7d29447817adbddvboxsync size_t pagelistsize,
561b8d2b46fb10887829b7e4d7d29447817adbddvboxsync struct seg *segp,
561b8d2b46fb10887829b7e4d7d29447817adbddvboxsync caddr_t addr,
561b8d2b46fb10887829b7e4d7d29447817adbddvboxsync enum seg_rw segaccess,
561b8d2b46fb10887829b7e4d7d29447817adbddvboxsync cred_t *credp
561b8d2b46fb10887829b7e4d7d29447817adbddvboxsync#if !defined(VBOX_VFS_SOLARIS_10U6)
561b8d2b46fb10887829b7e4d7d29447817adbddvboxsync , caller_context_t *ct
561b8d2b46fb10887829b7e4d7d29447817adbddvboxsync#endif
561b8d2b46fb10887829b7e4d7d29447817adbddvboxsync )
561b8d2b46fb10887829b7e4d7d29447817adbddvboxsync{
fb4eaa62a6bbeb82a89703d833d39339783feb4avboxsync int error = 0;
81c0cfc4db8e08dc6b8b365a25a71d3dae66a879vboxsync int is_recursive = 0;
fb4eaa62a6bbeb82a89703d833d39339783feb4avboxsync page_t **pageliststart = pagelist;
dbd602ecc07512999944bedae1e2d09c88f2298bvboxsync sfnode_t *node = VN2SFN(dvp);
dbd602ecc07512999944bedae1e2d09c88f2298bvboxsync ASSERT(node);
dbd602ecc07512999944bedae1e2d09c88f2298bvboxsync ASSERT(node->sf_file);
fb4eaa62a6bbeb82a89703d833d39339783feb4avboxsync
fb4eaa62a6bbeb82a89703d833d39339783feb4avboxsync if (segaccess == S_WRITE)
fb4eaa62a6bbeb82a89703d833d39339783feb4avboxsync return (ENOSYS); /* Will this ever happen? */
fb4eaa62a6bbeb82a89703d833d39339783feb4avboxsync
dbd602ecc07512999944bedae1e2d09c88f2298bvboxsync /* Don't bother about faultahead for now. */
fb4eaa62a6bbeb82a89703d833d39339783feb4avboxsync if (pagelist == NULL)
fb4eaa62a6bbeb82a89703d833d39339783feb4avboxsync return (0);
fb4eaa62a6bbeb82a89703d833d39339783feb4avboxsync
fb4eaa62a6bbeb82a89703d833d39339783feb4avboxsync if (len > pagelistsize)
fb4eaa62a6bbeb82a89703d833d39339783feb4avboxsync len = pagelistsize;
fb4eaa62a6bbeb82a89703d833d39339783feb4avboxsync else
fb4eaa62a6bbeb82a89703d833d39339783feb4avboxsync len = P2ROUNDUP(len, PAGESIZE);
fb4eaa62a6bbeb82a89703d833d39339783feb4avboxsync ASSERT(pagelistsize >= len);
fb4eaa62a6bbeb82a89703d833d39339783feb4avboxsync
dbd602ecc07512999944bedae1e2d09c88f2298bvboxsync if (protp)
dbd602ecc07512999944bedae1e2d09c88f2298bvboxsync *protp = PROT_ALL;
dbd602ecc07512999944bedae1e2d09c88f2298bvboxsync
81c0cfc4db8e08dc6b8b365a25a71d3dae66a879vboxsync /*
81c0cfc4db8e08dc6b8b365a25a71d3dae66a879vboxsync * The buffer passed to sffs_write may be mmap'd so we may get a
81c0cfc4db8e08dc6b8b365a25a71d3dae66a879vboxsync * pagefault there, in which case we'll end up here with this thread
81c0cfc4db8e08dc6b8b365a25a71d3dae66a879vboxsync * already owning the mutex. Mutexes aren't recursive.
81c0cfc4db8e08dc6b8b365a25a71d3dae66a879vboxsync */
81c0cfc4db8e08dc6b8b365a25a71d3dae66a879vboxsync if (mutex_owner(&sffs_lock) == curthread)
81c0cfc4db8e08dc6b8b365a25a71d3dae66a879vboxsync is_recursive = 1;
81c0cfc4db8e08dc6b8b365a25a71d3dae66a879vboxsync else
81c0cfc4db8e08dc6b8b365a25a71d3dae66a879vboxsync mutex_enter(&sffs_lock);
fb4eaa62a6bbeb82a89703d833d39339783feb4avboxsync
dbd602ecc07512999944bedae1e2d09c88f2298bvboxsync /* Don't map pages past end of the file. */
dbd602ecc07512999944bedae1e2d09c88f2298bvboxsync if (off + len > node->sf_stat.sf_size + PAGEOFFSET)
dbd602ecc07512999944bedae1e2d09c88f2298bvboxsync {
ae8a38ec189b100443c189854999758940b4a8f0vboxsync if (!is_recursive)
ae8a38ec189b100443c189854999758940b4a8f0vboxsync mutex_exit(&sffs_lock);
dbd602ecc07512999944bedae1e2d09c88f2298bvboxsync return (EFAULT);
dbd602ecc07512999944bedae1e2d09c88f2298bvboxsync }
dbd602ecc07512999944bedae1e2d09c88f2298bvboxsync
fb4eaa62a6bbeb82a89703d833d39339783feb4avboxsync while (len > 0)
fb4eaa62a6bbeb82a89703d833d39339783feb4avboxsync {
fb4eaa62a6bbeb82a89703d833d39339783feb4avboxsync /*
fb4eaa62a6bbeb82a89703d833d39339783feb4avboxsync * Look for pages in the requested offset range, or create them if we can't find any.
fb4eaa62a6bbeb82a89703d833d39339783feb4avboxsync */
fb4eaa62a6bbeb82a89703d833d39339783feb4avboxsync if ((*pagelist = page_lookup(dvp, off, SE_SHARED)) != NULL)
fb4eaa62a6bbeb82a89703d833d39339783feb4avboxsync *(pagelist + 1) = NULL;
fb4eaa62a6bbeb82a89703d833d39339783feb4avboxsync else if ((error = sffs_readpages(dvp, off, pagelist, pagelistsize, segp, addr, segaccess)) != 0)
fb4eaa62a6bbeb82a89703d833d39339783feb4avboxsync {
fb4eaa62a6bbeb82a89703d833d39339783feb4avboxsync while (pagelist > pageliststart)
fb4eaa62a6bbeb82a89703d833d39339783feb4avboxsync page_unlock(*--pagelist);
fb4eaa62a6bbeb82a89703d833d39339783feb4avboxsync
fb4eaa62a6bbeb82a89703d833d39339783feb4avboxsync *pagelist = NULL;
81c0cfc4db8e08dc6b8b365a25a71d3dae66a879vboxsync if (!is_recursive)
81c0cfc4db8e08dc6b8b365a25a71d3dae66a879vboxsync mutex_exit(&sffs_lock);
fb4eaa62a6bbeb82a89703d833d39339783feb4avboxsync return (error);
fb4eaa62a6bbeb82a89703d833d39339783feb4avboxsync }
fb4eaa62a6bbeb82a89703d833d39339783feb4avboxsync
fb4eaa62a6bbeb82a89703d833d39339783feb4avboxsync while (*pagelist)
fb4eaa62a6bbeb82a89703d833d39339783feb4avboxsync {
fb4eaa62a6bbeb82a89703d833d39339783feb4avboxsync ASSERT3U((*pagelist)->p_offset, ==, off);
fb4eaa62a6bbeb82a89703d833d39339783feb4avboxsync off += PAGESIZE;
fb4eaa62a6bbeb82a89703d833d39339783feb4avboxsync addr += PAGESIZE;
fb4eaa62a6bbeb82a89703d833d39339783feb4avboxsync if (len > 0)
fb4eaa62a6bbeb82a89703d833d39339783feb4avboxsync {
fb4eaa62a6bbeb82a89703d833d39339783feb4avboxsync ASSERT3U(len, >=, PAGESIZE);
fb4eaa62a6bbeb82a89703d833d39339783feb4avboxsync len -= PAGESIZE;
fb4eaa62a6bbeb82a89703d833d39339783feb4avboxsync }
fb4eaa62a6bbeb82a89703d833d39339783feb4avboxsync
fb4eaa62a6bbeb82a89703d833d39339783feb4avboxsync ASSERT3U(pagelistsize, >=, PAGESIZE);
fb4eaa62a6bbeb82a89703d833d39339783feb4avboxsync pagelistsize -= PAGESIZE;
fb4eaa62a6bbeb82a89703d833d39339783feb4avboxsync pagelist++;
fb4eaa62a6bbeb82a89703d833d39339783feb4avboxsync }
dbd602ecc07512999944bedae1e2d09c88f2298bvboxsync }
fb4eaa62a6bbeb82a89703d833d39339783feb4avboxsync
dbd602ecc07512999944bedae1e2d09c88f2298bvboxsync /*
dbd602ecc07512999944bedae1e2d09c88f2298bvboxsync * Fill the page list array with any pages left in the cache.
dbd602ecc07512999944bedae1e2d09c88f2298bvboxsync */
dbd602ecc07512999944bedae1e2d09c88f2298bvboxsync while ( pagelistsize > 0
dbd602ecc07512999944bedae1e2d09c88f2298bvboxsync && (*pagelist++ = page_lookup_nowait(dvp, off, SE_SHARED)))
dbd602ecc07512999944bedae1e2d09c88f2298bvboxsync {
dbd602ecc07512999944bedae1e2d09c88f2298bvboxsync off += PAGESIZE;
dbd602ecc07512999944bedae1e2d09c88f2298bvboxsync pagelistsize -= PAGESIZE;
fb4eaa62a6bbeb82a89703d833d39339783feb4avboxsync }
fb4eaa62a6bbeb82a89703d833d39339783feb4avboxsync
fb4eaa62a6bbeb82a89703d833d39339783feb4avboxsync *pagelist = NULL;
81c0cfc4db8e08dc6b8b365a25a71d3dae66a879vboxsync if (!is_recursive)
81c0cfc4db8e08dc6b8b365a25a71d3dae66a879vboxsync mutex_exit(&sffs_lock);
fb4eaa62a6bbeb82a89703d833d39339783feb4avboxsync return (error);
561b8d2b46fb10887829b7e4d7d29447817adbddvboxsync}
561b8d2b46fb10887829b7e4d7d29447817adbddvboxsync
561b8d2b46fb10887829b7e4d7d29447817adbddvboxsync
561b8d2b46fb10887829b7e4d7d29447817adbddvboxsync/*ARGSUSED*/
561b8d2b46fb10887829b7e4d7d29447817adbddvboxsyncstatic int
561b8d2b46fb10887829b7e4d7d29447817adbddvboxsyncsffs_putpage(
561b8d2b46fb10887829b7e4d7d29447817adbddvboxsync vnode_t *dvp,
561b8d2b46fb10887829b7e4d7d29447817adbddvboxsync offset_t off,
561b8d2b46fb10887829b7e4d7d29447817adbddvboxsync size_t len,
561b8d2b46fb10887829b7e4d7d29447817adbddvboxsync int flags,
561b8d2b46fb10887829b7e4d7d29447817adbddvboxsync cred_t *credp
561b8d2b46fb10887829b7e4d7d29447817adbddvboxsync#if !defined(VBOX_VFS_SOLARIS_10U6)
561b8d2b46fb10887829b7e4d7d29447817adbddvboxsync , caller_context_t *ct
561b8d2b46fb10887829b7e4d7d29447817adbddvboxsync#endif
561b8d2b46fb10887829b7e4d7d29447817adbddvboxsync )
561b8d2b46fb10887829b7e4d7d29447817adbddvboxsync{
fb4eaa62a6bbeb82a89703d833d39339783feb4avboxsync /*
bf68374f2c57e885807b47ffe327149dbb6fc6bfvboxsync * We don't support PROT_WRITE mmaps.
fb4eaa62a6bbeb82a89703d833d39339783feb4avboxsync */
fb4eaa62a6bbeb82a89703d833d39339783feb4avboxsync return (ENOSYS);
561b8d2b46fb10887829b7e4d7d29447817adbddvboxsync}
561b8d2b46fb10887829b7e4d7d29447817adbddvboxsync
561b8d2b46fb10887829b7e4d7d29447817adbddvboxsync
a2907076474e923411cc5046492a88787ba377fevboxsync/*ARGSUSED*/
a2907076474e923411cc5046492a88787ba377fevboxsyncstatic int
a2907076474e923411cc5046492a88787ba377fevboxsyncsffs_discardpage(
a2907076474e923411cc5046492a88787ba377fevboxsync vnode_t *dvp,
a2907076474e923411cc5046492a88787ba377fevboxsync page_t *ppage,
a2907076474e923411cc5046492a88787ba377fevboxsync u_offset_t *poff,
a2907076474e923411cc5046492a88787ba377fevboxsync size_t *plen,
a2907076474e923411cc5046492a88787ba377fevboxsync int flags,
a2907076474e923411cc5046492a88787ba377fevboxsync cred_t *pcred)
a2907076474e923411cc5046492a88787ba377fevboxsync{
a2907076474e923411cc5046492a88787ba377fevboxsync /*
ebbe78c52653f516133cf68ac0199b35c1d96ddfvboxsync * This would not get invoked i.e. via pvn_vplist_dirty() since we don't support
ebbe78c52653f516133cf68ac0199b35c1d96ddfvboxsync * PROT_WRITE mmaps and therefore will not have dirty pages.
a2907076474e923411cc5046492a88787ba377fevboxsync */
a2907076474e923411cc5046492a88787ba377fevboxsync pvn_write_done(ppage, B_INVAL | B_ERROR | B_FORCE);
a2907076474e923411cc5046492a88787ba377fevboxsync return (0);
a2907076474e923411cc5046492a88787ba377fevboxsync}
a2907076474e923411cc5046492a88787ba377fevboxsync
a2907076474e923411cc5046492a88787ba377fevboxsync
561b8d2b46fb10887829b7e4d7d29447817adbddvboxsync/*ARGSUSED*/
561b8d2b46fb10887829b7e4d7d29447817adbddvboxsyncstatic int
561b8d2b46fb10887829b7e4d7d29447817adbddvboxsyncsffs_map(
561b8d2b46fb10887829b7e4d7d29447817adbddvboxsync vnode_t *dvp,
561b8d2b46fb10887829b7e4d7d29447817adbddvboxsync offset_t off,
561b8d2b46fb10887829b7e4d7d29447817adbddvboxsync struct as *asp,
561b8d2b46fb10887829b7e4d7d29447817adbddvboxsync caddr_t *addrp,
561b8d2b46fb10887829b7e4d7d29447817adbddvboxsync size_t len,
561b8d2b46fb10887829b7e4d7d29447817adbddvboxsync uchar_t prot,
561b8d2b46fb10887829b7e4d7d29447817adbddvboxsync uchar_t maxprot,
561b8d2b46fb10887829b7e4d7d29447817adbddvboxsync uint_t flags,
561b8d2b46fb10887829b7e4d7d29447817adbddvboxsync cred_t *credp
561b8d2b46fb10887829b7e4d7d29447817adbddvboxsync#if !defined(VBOX_VFS_SOLARIS_10U6)
561b8d2b46fb10887829b7e4d7d29447817adbddvboxsync , caller_context_t *ct
561b8d2b46fb10887829b7e4d7d29447817adbddvboxsync#endif
561b8d2b46fb10887829b7e4d7d29447817adbddvboxsync )
561b8d2b46fb10887829b7e4d7d29447817adbddvboxsync{
561b8d2b46fb10887829b7e4d7d29447817adbddvboxsync /*
fb4eaa62a6bbeb82a89703d833d39339783feb4avboxsync * Invocation: mmap()->smmap_common()->VOP_MAP()->sffs_map(). Once the
fb4eaa62a6bbeb82a89703d833d39339783feb4avboxsync * segment driver creates the new segment via segvn_create(), it'll
fb4eaa62a6bbeb82a89703d833d39339783feb4avboxsync * invoke down the line VOP_ADDMAP()->sffs_addmap()
561b8d2b46fb10887829b7e4d7d29447817adbddvboxsync */
0360c14b2b3750bd2c90d935775ccdb05da307c9vboxsync int error = 0;
fb4eaa62a6bbeb82a89703d833d39339783feb4avboxsync sfnode_t *node = VN2SFN(dvp);
fb4eaa62a6bbeb82a89703d833d39339783feb4avboxsync ASSERT(node);
a2c55ac179b1b57a4f11884f0cb580b0ac14bc82vboxsync if ((flags & MAP_SHARED) && (prot & PROT_WRITE))
561b8d2b46fb10887829b7e4d7d29447817adbddvboxsync return (ENOTSUP);
561b8d2b46fb10887829b7e4d7d29447817adbddvboxsync
561b8d2b46fb10887829b7e4d7d29447817adbddvboxsync if (off < 0 || len > MAXOFFSET_T - off)
561b8d2b46fb10887829b7e4d7d29447817adbddvboxsync return (ENXIO);
561b8d2b46fb10887829b7e4d7d29447817adbddvboxsync
561b8d2b46fb10887829b7e4d7d29447817adbddvboxsync if (dvp->v_type != VREG)
561b8d2b46fb10887829b7e4d7d29447817adbddvboxsync return (ENODEV);
561b8d2b46fb10887829b7e4d7d29447817adbddvboxsync
561b8d2b46fb10887829b7e4d7d29447817adbddvboxsync if (dvp->v_flag & VNOMAP)
561b8d2b46fb10887829b7e4d7d29447817adbddvboxsync return (ENOSYS);
561b8d2b46fb10887829b7e4d7d29447817adbddvboxsync
fb4eaa62a6bbeb82a89703d833d39339783feb4avboxsync if (vn_has_mandatory_locks(dvp, node->sf_stat.sf_mode))
fb4eaa62a6bbeb82a89703d833d39339783feb4avboxsync return (EAGAIN);
fb4eaa62a6bbeb82a89703d833d39339783feb4avboxsync
561b8d2b46fb10887829b7e4d7d29447817adbddvboxsync mutex_enter(&sffs_lock);
561b8d2b46fb10887829b7e4d7d29447817adbddvboxsync as_rangelock(asp);
561b8d2b46fb10887829b7e4d7d29447817adbddvboxsync
0360c14b2b3750bd2c90d935775ccdb05da307c9vboxsync#if defined(VBOX_VFS_SOLARIS_10U6)
0360c14b2b3750bd2c90d935775ccdb05da307c9vboxsync if ((flags & MAP_FIXED) == 0)
0360c14b2b3750bd2c90d935775ccdb05da307c9vboxsync {
0360c14b2b3750bd2c90d935775ccdb05da307c9vboxsync map_addr(addrp, len, off, 1, flags);
0360c14b2b3750bd2c90d935775ccdb05da307c9vboxsync if (*addrp == NULL)
0360c14b2b3750bd2c90d935775ccdb05da307c9vboxsync error = ENOMEM;
0360c14b2b3750bd2c90d935775ccdb05da307c9vboxsync }
0360c14b2b3750bd2c90d935775ccdb05da307c9vboxsync else
0360c14b2b3750bd2c90d935775ccdb05da307c9vboxsync as_unmap(asp, *addrp, len); /* User specified address, remove any previous mappings */
0360c14b2b3750bd2c90d935775ccdb05da307c9vboxsync#else
561b8d2b46fb10887829b7e4d7d29447817adbddvboxsync error = choose_addr(asp, addrp, len, off, ADDR_VACALIGN, flags);
0360c14b2b3750bd2c90d935775ccdb05da307c9vboxsync#endif
0360c14b2b3750bd2c90d935775ccdb05da307c9vboxsync
0360c14b2b3750bd2c90d935775ccdb05da307c9vboxsync if (error)
561b8d2b46fb10887829b7e4d7d29447817adbddvboxsync {
0360c14b2b3750bd2c90d935775ccdb05da307c9vboxsync as_rangeunlock(asp);
0360c14b2b3750bd2c90d935775ccdb05da307c9vboxsync mutex_exit(&sffs_lock);
0360c14b2b3750bd2c90d935775ccdb05da307c9vboxsync return (error);
561b8d2b46fb10887829b7e4d7d29447817adbddvboxsync }
561b8d2b46fb10887829b7e4d7d29447817adbddvboxsync
0360c14b2b3750bd2c90d935775ccdb05da307c9vboxsync segvn_crargs_t vnodeargs;
0360c14b2b3750bd2c90d935775ccdb05da307c9vboxsync memset(&vnodeargs, 0, sizeof(vnodeargs));
0360c14b2b3750bd2c90d935775ccdb05da307c9vboxsync vnodeargs.vp = dvp;
0360c14b2b3750bd2c90d935775ccdb05da307c9vboxsync vnodeargs.cred = credp;
0360c14b2b3750bd2c90d935775ccdb05da307c9vboxsync vnodeargs.offset = off;
0360c14b2b3750bd2c90d935775ccdb05da307c9vboxsync vnodeargs.type = flags & MAP_TYPE;
0360c14b2b3750bd2c90d935775ccdb05da307c9vboxsync vnodeargs.prot = prot;
0360c14b2b3750bd2c90d935775ccdb05da307c9vboxsync vnodeargs.maxprot = maxprot;
0360c14b2b3750bd2c90d935775ccdb05da307c9vboxsync vnodeargs.flags = flags & ~MAP_TYPE;
0360c14b2b3750bd2c90d935775ccdb05da307c9vboxsync vnodeargs.amp = NULL; /* anon. mapping */
0360c14b2b3750bd2c90d935775ccdb05da307c9vboxsync vnodeargs.szc = 0; /* preferred page size code */
0360c14b2b3750bd2c90d935775ccdb05da307c9vboxsync vnodeargs.lgrp_mem_policy_flags = 0;
0360c14b2b3750bd2c90d935775ccdb05da307c9vboxsync
0360c14b2b3750bd2c90d935775ccdb05da307c9vboxsync error = as_map(asp, *addrp, len, segvn_create, &vnodeargs);
0360c14b2b3750bd2c90d935775ccdb05da307c9vboxsync
561b8d2b46fb10887829b7e4d7d29447817adbddvboxsync as_rangeunlock(asp);
561b8d2b46fb10887829b7e4d7d29447817adbddvboxsync mutex_exit(&sffs_lock);
561b8d2b46fb10887829b7e4d7d29447817adbddvboxsync return (error);
561b8d2b46fb10887829b7e4d7d29447817adbddvboxsync}
561b8d2b46fb10887829b7e4d7d29447817adbddvboxsync
561b8d2b46fb10887829b7e4d7d29447817adbddvboxsync
561b8d2b46fb10887829b7e4d7d29447817adbddvboxsync/*ARGSUSED*/
561b8d2b46fb10887829b7e4d7d29447817adbddvboxsyncstatic int
561b8d2b46fb10887829b7e4d7d29447817adbddvboxsyncsffs_addmap(
561b8d2b46fb10887829b7e4d7d29447817adbddvboxsync vnode_t *dvp,
561b8d2b46fb10887829b7e4d7d29447817adbddvboxsync offset_t off,
561b8d2b46fb10887829b7e4d7d29447817adbddvboxsync struct as *asp,
561b8d2b46fb10887829b7e4d7d29447817adbddvboxsync caddr_t addr,
561b8d2b46fb10887829b7e4d7d29447817adbddvboxsync size_t len,
561b8d2b46fb10887829b7e4d7d29447817adbddvboxsync uchar_t prot,
561b8d2b46fb10887829b7e4d7d29447817adbddvboxsync uchar_t maxprot,
561b8d2b46fb10887829b7e4d7d29447817adbddvboxsync uint_t flags,
561b8d2b46fb10887829b7e4d7d29447817adbddvboxsync cred_t *credp
561b8d2b46fb10887829b7e4d7d29447817adbddvboxsync#if !defined(VBOX_VFS_SOLARIS_10U6)
561b8d2b46fb10887829b7e4d7d29447817adbddvboxsync , caller_context_t *ct
561b8d2b46fb10887829b7e4d7d29447817adbddvboxsync#endif
561b8d2b46fb10887829b7e4d7d29447817adbddvboxsync )
561b8d2b46fb10887829b7e4d7d29447817adbddvboxsync{
fb4eaa62a6bbeb82a89703d833d39339783feb4avboxsync if (dvp->v_flag & VNOMAP)
fb4eaa62a6bbeb82a89703d833d39339783feb4avboxsync return (ENOSYS);
561b8d2b46fb10887829b7e4d7d29447817adbddvboxsync return (0);
561b8d2b46fb10887829b7e4d7d29447817adbddvboxsync}
561b8d2b46fb10887829b7e4d7d29447817adbddvboxsync
561b8d2b46fb10887829b7e4d7d29447817adbddvboxsync
561b8d2b46fb10887829b7e4d7d29447817adbddvboxsync/*ARGSUSED*/
561b8d2b46fb10887829b7e4d7d29447817adbddvboxsyncstatic int
561b8d2b46fb10887829b7e4d7d29447817adbddvboxsyncsffs_delmap(
561b8d2b46fb10887829b7e4d7d29447817adbddvboxsync vnode_t *dvp,
561b8d2b46fb10887829b7e4d7d29447817adbddvboxsync offset_t off,
561b8d2b46fb10887829b7e4d7d29447817adbddvboxsync struct as *asp,
561b8d2b46fb10887829b7e4d7d29447817adbddvboxsync caddr_t addr,
561b8d2b46fb10887829b7e4d7d29447817adbddvboxsync size_t len,
561b8d2b46fb10887829b7e4d7d29447817adbddvboxsync uint_t prot,
561b8d2b46fb10887829b7e4d7d29447817adbddvboxsync uint_t maxprot,
561b8d2b46fb10887829b7e4d7d29447817adbddvboxsync uint_t flags,
561b8d2b46fb10887829b7e4d7d29447817adbddvboxsync cred_t *credp
561b8d2b46fb10887829b7e4d7d29447817adbddvboxsync#if !defined(VBOX_VFS_SOLARIS_10U6)
561b8d2b46fb10887829b7e4d7d29447817adbddvboxsync , caller_context_t *ct
561b8d2b46fb10887829b7e4d7d29447817adbddvboxsync#endif
561b8d2b46fb10887829b7e4d7d29447817adbddvboxsync )
561b8d2b46fb10887829b7e4d7d29447817adbddvboxsync{
fb4eaa62a6bbeb82a89703d833d39339783feb4avboxsync if (dvp->v_flag & VNOMAP)
fb4eaa62a6bbeb82a89703d833d39339783feb4avboxsync return (ENOSYS);
bf68374f2c57e885807b47ffe327149dbb6fc6bfvboxsync
561b8d2b46fb10887829b7e4d7d29447817adbddvboxsync return (0);
561b8d2b46fb10887829b7e4d7d29447817adbddvboxsync}
a2907076474e923411cc5046492a88787ba377fevboxsync#endif /* VBOXVFS_WITH_MMAP */
561b8d2b46fb10887829b7e4d7d29447817adbddvboxsync
561b8d2b46fb10887829b7e4d7d29447817adbddvboxsync
99eccc8f34de2d4b6af556ba2f5f0c756af237c7vboxsync/*ARGSUSED*/
99eccc8f34de2d4b6af556ba2f5f0c756af237c7vboxsyncstatic int
99eccc8f34de2d4b6af556ba2f5f0c756af237c7vboxsyncsffs_readlink(
99eccc8f34de2d4b6af556ba2f5f0c756af237c7vboxsync vnode_t *vp,
99eccc8f34de2d4b6af556ba2f5f0c756af237c7vboxsync uio_t *uiop,
99eccc8f34de2d4b6af556ba2f5f0c756af237c7vboxsync cred_t *cred
99eccc8f34de2d4b6af556ba2f5f0c756af237c7vboxsync#if !defined(VBOX_VFS_SOLARIS_10U6)
99eccc8f34de2d4b6af556ba2f5f0c756af237c7vboxsync ,
99eccc8f34de2d4b6af556ba2f5f0c756af237c7vboxsync caller_context_t *ct
99eccc8f34de2d4b6af556ba2f5f0c756af237c7vboxsync#endif
99eccc8f34de2d4b6af556ba2f5f0c756af237c7vboxsync )
99eccc8f34de2d4b6af556ba2f5f0c756af237c7vboxsync{
99eccc8f34de2d4b6af556ba2f5f0c756af237c7vboxsync sfnode_t *node;
99eccc8f34de2d4b6af556ba2f5f0c756af237c7vboxsync int error = 0;
99eccc8f34de2d4b6af556ba2f5f0c756af237c7vboxsync char *target = NULL;
99eccc8f34de2d4b6af556ba2f5f0c756af237c7vboxsync
99eccc8f34de2d4b6af556ba2f5f0c756af237c7vboxsync if (uiop->uio_iovcnt != 1)
99eccc8f34de2d4b6af556ba2f5f0c756af237c7vboxsync return (EINVAL);
99eccc8f34de2d4b6af556ba2f5f0c756af237c7vboxsync
99eccc8f34de2d4b6af556ba2f5f0c756af237c7vboxsync if (vp->v_type != VLNK)
99eccc8f34de2d4b6af556ba2f5f0c756af237c7vboxsync return (EINVAL);
99eccc8f34de2d4b6af556ba2f5f0c756af237c7vboxsync
99eccc8f34de2d4b6af556ba2f5f0c756af237c7vboxsync mutex_enter(&sffs_lock);
99eccc8f34de2d4b6af556ba2f5f0c756af237c7vboxsync node = VN2SFN(vp);
99eccc8f34de2d4b6af556ba2f5f0c756af237c7vboxsync
99eccc8f34de2d4b6af556ba2f5f0c756af237c7vboxsync target = kmem_alloc(MAXPATHLEN, KM_SLEEP);
99eccc8f34de2d4b6af556ba2f5f0c756af237c7vboxsync
99eccc8f34de2d4b6af556ba2f5f0c756af237c7vboxsync error = sfprov_readlink(node->sf_sffs->sf_handle, node->sf_path, target,
99eccc8f34de2d4b6af556ba2f5f0c756af237c7vboxsync MAXPATHLEN);
99eccc8f34de2d4b6af556ba2f5f0c756af237c7vboxsync if (error)
99eccc8f34de2d4b6af556ba2f5f0c756af237c7vboxsync goto done;
99eccc8f34de2d4b6af556ba2f5f0c756af237c7vboxsync
99eccc8f34de2d4b6af556ba2f5f0c756af237c7vboxsync error = uiomove(target, strlen(target), UIO_READ, uiop);
99eccc8f34de2d4b6af556ba2f5f0c756af237c7vboxsync
99eccc8f34de2d4b6af556ba2f5f0c756af237c7vboxsyncdone:
99eccc8f34de2d4b6af556ba2f5f0c756af237c7vboxsync mutex_exit(&sffs_lock);
99eccc8f34de2d4b6af556ba2f5f0c756af237c7vboxsync if (target)
99eccc8f34de2d4b6af556ba2f5f0c756af237c7vboxsync kmem_free(target, MAXPATHLEN);
99eccc8f34de2d4b6af556ba2f5f0c756af237c7vboxsync return (error);
99eccc8f34de2d4b6af556ba2f5f0c756af237c7vboxsync}
99eccc8f34de2d4b6af556ba2f5f0c756af237c7vboxsync
99eccc8f34de2d4b6af556ba2f5f0c756af237c7vboxsync
99eccc8f34de2d4b6af556ba2f5f0c756af237c7vboxsync/*ARGSUSED*/
99eccc8f34de2d4b6af556ba2f5f0c756af237c7vboxsyncstatic int
99eccc8f34de2d4b6af556ba2f5f0c756af237c7vboxsyncsffs_symlink(
99eccc8f34de2d4b6af556ba2f5f0c756af237c7vboxsync vnode_t *dvp,
99eccc8f34de2d4b6af556ba2f5f0c756af237c7vboxsync char *linkname,
99eccc8f34de2d4b6af556ba2f5f0c756af237c7vboxsync vattr_t *vap,
99eccc8f34de2d4b6af556ba2f5f0c756af237c7vboxsync char *target,
99eccc8f34de2d4b6af556ba2f5f0c756af237c7vboxsync cred_t *cred
99eccc8f34de2d4b6af556ba2f5f0c756af237c7vboxsync#if !defined(VBOX_VFS_SOLARIS_10U6)
99eccc8f34de2d4b6af556ba2f5f0c756af237c7vboxsync ,
99eccc8f34de2d4b6af556ba2f5f0c756af237c7vboxsync caller_context_t *ct,
99eccc8f34de2d4b6af556ba2f5f0c756af237c7vboxsync int flags
99eccc8f34de2d4b6af556ba2f5f0c756af237c7vboxsync#endif
99eccc8f34de2d4b6af556ba2f5f0c756af237c7vboxsync )
99eccc8f34de2d4b6af556ba2f5f0c756af237c7vboxsync{
99eccc8f34de2d4b6af556ba2f5f0c756af237c7vboxsync sfnode_t *dir;
99eccc8f34de2d4b6af556ba2f5f0c756af237c7vboxsync sfnode_t *node;
99eccc8f34de2d4b6af556ba2f5f0c756af237c7vboxsync sffs_stat_t stat;
99eccc8f34de2d4b6af556ba2f5f0c756af237c7vboxsync int error = 0;
99eccc8f34de2d4b6af556ba2f5f0c756af237c7vboxsync char *fullpath;
99eccc8f34de2d4b6af556ba2f5f0c756af237c7vboxsync
99eccc8f34de2d4b6af556ba2f5f0c756af237c7vboxsync /*
99eccc8f34de2d4b6af556ba2f5f0c756af237c7vboxsync * These should never happen
99eccc8f34de2d4b6af556ba2f5f0c756af237c7vboxsync */
99eccc8f34de2d4b6af556ba2f5f0c756af237c7vboxsync ASSERT(linkname != NULL);
99eccc8f34de2d4b6af556ba2f5f0c756af237c7vboxsync ASSERT(strcmp(linkname, "") != 0);
99eccc8f34de2d4b6af556ba2f5f0c756af237c7vboxsync ASSERT(strcmp(linkname, ".") != 0);
99eccc8f34de2d4b6af556ba2f5f0c756af237c7vboxsync ASSERT(strcmp(linkname, "..") != 0);
99eccc8f34de2d4b6af556ba2f5f0c756af237c7vboxsync
99eccc8f34de2d4b6af556ba2f5f0c756af237c7vboxsync /*
99eccc8f34de2d4b6af556ba2f5f0c756af237c7vboxsync * Basic checks.
99eccc8f34de2d4b6af556ba2f5f0c756af237c7vboxsync */
99eccc8f34de2d4b6af556ba2f5f0c756af237c7vboxsync if (vap->va_type != VLNK)
99eccc8f34de2d4b6af556ba2f5f0c756af237c7vboxsync return (EINVAL);
99eccc8f34de2d4b6af556ba2f5f0c756af237c7vboxsync
99eccc8f34de2d4b6af556ba2f5f0c756af237c7vboxsync mutex_enter(&sffs_lock);
99eccc8f34de2d4b6af556ba2f5f0c756af237c7vboxsync
e7bdfd4ea69601e5b2ddaf9a6794d3ab9f24e5e8vboxsync if (sfnode_lookup(VN2SFN(dvp), linkname, VNON, 0, NULL, 0, NULL) !=
e7bdfd4ea69601e5b2ddaf9a6794d3ab9f24e5e8vboxsync NULL) {
99eccc8f34de2d4b6af556ba2f5f0c756af237c7vboxsync error = EEXIST;
99eccc8f34de2d4b6af556ba2f5f0c756af237c7vboxsync goto done;
99eccc8f34de2d4b6af556ba2f5f0c756af237c7vboxsync }
99eccc8f34de2d4b6af556ba2f5f0c756af237c7vboxsync
99eccc8f34de2d4b6af556ba2f5f0c756af237c7vboxsync dir = VN2SFN(dvp);
99eccc8f34de2d4b6af556ba2f5f0c756af237c7vboxsync error = sfnode_access(dir, VWRITE, cred);
99eccc8f34de2d4b6af556ba2f5f0c756af237c7vboxsync if (error)
99eccc8f34de2d4b6af556ba2f5f0c756af237c7vboxsync goto done;
99eccc8f34de2d4b6af556ba2f5f0c756af237c7vboxsync
99eccc8f34de2d4b6af556ba2f5f0c756af237c7vboxsync /*
99eccc8f34de2d4b6af556ba2f5f0c756af237c7vboxsync * Create symlink. Note that we ignore vap->va_mode because generally
99eccc8f34de2d4b6af556ba2f5f0c756af237c7vboxsync * we can't change the attributes of the symlink itself.
99eccc8f34de2d4b6af556ba2f5f0c756af237c7vboxsync */
99eccc8f34de2d4b6af556ba2f5f0c756af237c7vboxsync fullpath = sfnode_construct_path(dir, linkname);
99eccc8f34de2d4b6af556ba2f5f0c756af237c7vboxsync error = sfprov_symlink(dir->sf_sffs->sf_handle, fullpath, target,
99eccc8f34de2d4b6af556ba2f5f0c756af237c7vboxsync &stat);
99eccc8f34de2d4b6af556ba2f5f0c756af237c7vboxsync kmem_free(fullpath, strlen(fullpath) + 1);
99eccc8f34de2d4b6af556ba2f5f0c756af237c7vboxsync if (error)
99eccc8f34de2d4b6af556ba2f5f0c756af237c7vboxsync goto done;
99eccc8f34de2d4b6af556ba2f5f0c756af237c7vboxsync
e7bdfd4ea69601e5b2ddaf9a6794d3ab9f24e5e8vboxsync node = sfnode_lookup(dir, linkname, VLNK, 0, &stat,
e7bdfd4ea69601e5b2ddaf9a6794d3ab9f24e5e8vboxsync sfnode_cur_time_usec(), NULL);
99eccc8f34de2d4b6af556ba2f5f0c756af237c7vboxsync
99eccc8f34de2d4b6af556ba2f5f0c756af237c7vboxsync sfnode_invalidate_stat_cache(dir);
99eccc8f34de2d4b6af556ba2f5f0c756af237c7vboxsync sfnode_clear_dir_list(dir);
99eccc8f34de2d4b6af556ba2f5f0c756af237c7vboxsync
99eccc8f34de2d4b6af556ba2f5f0c756af237c7vboxsyncdone:
99eccc8f34de2d4b6af556ba2f5f0c756af237c7vboxsync mutex_exit(&sffs_lock);
99eccc8f34de2d4b6af556ba2f5f0c756af237c7vboxsync return (error);
99eccc8f34de2d4b6af556ba2f5f0c756af237c7vboxsync}
99eccc8f34de2d4b6af556ba2f5f0c756af237c7vboxsync
99eccc8f34de2d4b6af556ba2f5f0c756af237c7vboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync/*ARGSUSED*/
1403063c7e0c0a072d59e323b66068b06278fb9avboxsyncstatic int
1403063c7e0c0a072d59e323b66068b06278fb9avboxsyncsffs_remove(
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync vnode_t *dvp,
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync char *name,
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync cred_t *cred,
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync caller_context_t *ct,
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync int flags)
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync{
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync vnode_t *vp;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync sfnode_t *node;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync int error;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync /*
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync * These should never happen
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync */
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync ASSERT(name != NULL);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync ASSERT(strcmp(name, "..") != 0);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync error = sffs_lookup(dvp, name, &vp,
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync NULL, 0, NULL, cred, ct, NULL, NULL);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync if (error)
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync return (error);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync node = VN2SFN(vp);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync mutex_enter(&sffs_lock);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync error = sfnode_access(VN2SFN(dvp), VEXEC | VWRITE, cred);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync if (error)
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync goto done;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync /*
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync * If anything else is using this vnode, then fail the remove.
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync * Why? Windows hosts can't sfprov_remove() a file that is open,
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync * so we have to sfprov_close() it first.
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync * There is no errno for this - since it's not a problem on UNIX,
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync * but ETXTBSY is the closest.
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync */
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync if (node->sf_file != NULL) {
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync if (vp->v_count > 1) {
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync error = ETXTBSY;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync goto done;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync }
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync (void)sfprov_close(node->sf_file);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync node->sf_file = NULL;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync }
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync /*
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync * Remove the file on the host and mark the node as stale.
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync */
6479169ec893c18a646cec595e4e214492d180f0vboxsync sfnode_invalidate_stat_cache(VN2SFN(dvp));
6479169ec893c18a646cec595e4e214492d180f0vboxsync
99eccc8f34de2d4b6af556ba2f5f0c756af237c7vboxsync error = sfprov_remove(node->sf_sffs->sf_handle, node->sf_path,
99eccc8f34de2d4b6af556ba2f5f0c756af237c7vboxsync node->sf_type == VLNK);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync if (error == ENOENT || error == 0)
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync sfnode_make_stale(node);
f48c3167a0f99da174686b66dc4e666f38ecae46vboxsync
f48c3167a0f99da174686b66dc4e666f38ecae46vboxsync if (node->sf_parent)
f48c3167a0f99da174686b66dc4e666f38ecae46vboxsync sfnode_clear_dir_list(node->sf_parent);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsyncdone:
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync mutex_exit(&sffs_lock);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync VN_RELE(vp);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync return (error);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync}
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync/*ARGSUSED*/
1403063c7e0c0a072d59e323b66068b06278fb9avboxsyncstatic int
1403063c7e0c0a072d59e323b66068b06278fb9avboxsyncsffs_rename(
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync vnode_t *old_dir,
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync char *old_nm,
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync vnode_t *new_dir,
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync char *new_nm,
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync cred_t *cred,
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync caller_context_t *ct,
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync int flags)
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync{
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync char *newpath;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync int error;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync sfnode_t *node;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync if (strcmp(new_nm, "") == 0 ||
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync strcmp(new_nm, ".") == 0 ||
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync strcmp(new_nm, "..") == 0 ||
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync strcmp(old_nm, "") == 0 ||
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync strcmp(old_nm, ".") == 0 ||
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync strcmp(old_nm, "..") == 0)
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync return (EINVAL);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync /*
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync * make sure we have permission to do the rename
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync */
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync mutex_enter(&sffs_lock);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync error = sfnode_access(VN2SFN(old_dir), VEXEC | VWRITE, cred);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync if (error == 0 && new_dir != old_dir)
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync error = sfnode_access(VN2SFN(new_dir), VEXEC | VWRITE, cred);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync if (error)
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync goto done;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
e7bdfd4ea69601e5b2ddaf9a6794d3ab9f24e5e8vboxsync node = sfnode_lookup(VN2SFN(old_dir), old_nm, VNON, 0, NULL, 0, NULL);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync if (node == NULL) {
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync error = ENOENT;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync goto done;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync }
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync /*
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync * Rename the file on the host and in our caches.
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync */
6479169ec893c18a646cec595e4e214492d180f0vboxsync sfnode_invalidate_stat_cache(node);
6479169ec893c18a646cec595e4e214492d180f0vboxsync sfnode_invalidate_stat_cache(VN2SFN(old_dir));
6479169ec893c18a646cec595e4e214492d180f0vboxsync sfnode_invalidate_stat_cache(VN2SFN(new_dir));
6479169ec893c18a646cec595e4e214492d180f0vboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync newpath = sfnode_construct_path(VN2SFN(new_dir), new_nm);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync error = sfprov_rename(node->sf_sffs->sf_handle, node->sf_path, newpath,
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync node->sf_type == VDIR);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync if (error == 0)
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync sfnode_rename(node, VN2SFN(new_dir), newpath);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync else {
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync kmem_free(newpath, strlen(newpath) + 1);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync if (error == ENOENT)
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync sfnode_make_stale(node);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync }
1403063c7e0c0a072d59e323b66068b06278fb9avboxsyncdone:
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync mutex_exit(&sffs_lock);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync return (error);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync}
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync/*ARGSUSED*/
1403063c7e0c0a072d59e323b66068b06278fb9avboxsyncstatic int
1403063c7e0c0a072d59e323b66068b06278fb9avboxsyncsffs_fsync(vnode_t *vp, int flag, cred_t *cr, caller_context_t *ct)
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync{
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync sfnode_t *node;
7d7942380dbc581fdb6100a14cd1500605ab4f24vboxsync int error;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync /*
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync * Ask the host to sync any data it may have cached for open files.
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync */
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync mutex_enter(&sffs_lock);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync node = VN2SFN(vp);
7d7942380dbc581fdb6100a14cd1500605ab4f24vboxsync if (node->sf_file == NULL)
7d7942380dbc581fdb6100a14cd1500605ab4f24vboxsync error = EBADF;
7d7942380dbc581fdb6100a14cd1500605ab4f24vboxsync else if (node->sf_sffs->sf_fsync)
7d7942380dbc581fdb6100a14cd1500605ab4f24vboxsync error = sfprov_fsync(node->sf_file);
7d7942380dbc581fdb6100a14cd1500605ab4f24vboxsync else
7d7942380dbc581fdb6100a14cd1500605ab4f24vboxsync error = 0;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync mutex_exit(&sffs_lock);
7d7942380dbc581fdb6100a14cd1500605ab4f24vboxsync return (error);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync}
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync/*
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync * This may be the last reference, possibly time to close the file and
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync * destroy the vnode. If the sfnode is stale, we'll destroy that too.
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync */
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync/*ARGSUSED*/
1403063c7e0c0a072d59e323b66068b06278fb9avboxsyncstatic void
5738c06d9baa1f0abbb5b0442051072001395b1avboxsync#if defined(VBOX_VFS_SOLARIS_10U6)
5738c06d9baa1f0abbb5b0442051072001395b1avboxsyncsffs_inactive(vnode_t *vp, cred_t *cr)
5738c06d9baa1f0abbb5b0442051072001395b1avboxsync#else
1403063c7e0c0a072d59e323b66068b06278fb9avboxsyncsffs_inactive(vnode_t *vp, cred_t *cr, caller_context_t *ct)
5738c06d9baa1f0abbb5b0442051072001395b1avboxsync#endif
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync{
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync sfnode_t *node;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync /*
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync * nothing to do if this isn't the last use
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync */
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync mutex_enter(&sffs_lock);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync node = VN2SFN(vp);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync mutex_enter(&vp->v_lock);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync if (vp->v_count > 1) {
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync --vp->v_count;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync mutex_exit(&vp->v_lock);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync mutex_exit(&sffs_lock);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync return;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync }
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
a2907076474e923411cc5046492a88787ba377fevboxsync if (vn_has_cached_data(vp)) {
a2907076474e923411cc5046492a88787ba377fevboxsync#ifdef VBOXVFS_WITH_MMAP
a2907076474e923411cc5046492a88787ba377fevboxsync /* We're fine with releasing the vnode lock here as we should be covered by the sffs_lock */
a2907076474e923411cc5046492a88787ba377fevboxsync mutex_exit(&vp->v_lock);
ebbe78c52653f516133cf68ac0199b35c1d96ddfvboxsync /* We won't have any dirty pages, this will just invalidate (destroy) the pages and move it to the cachelist. */
a2907076474e923411cc5046492a88787ba377fevboxsync pvn_vplist_dirty(vp, 0 /* offset */, sffs_discardpage, B_INVAL, cr);
a2907076474e923411cc5046492a88787ba377fevboxsync mutex_enter(&vp->v_lock);
a2907076474e923411cc5046492a88787ba377fevboxsync#else
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync panic("sffs_inactive() found cached data");
a2907076474e923411cc5046492a88787ba377fevboxsync#endif
a2907076474e923411cc5046492a88787ba377fevboxsync }
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync /*
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync * destroy the vnode
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync */
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync node->sf_vnode = NULL;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync mutex_exit(&vp->v_lock);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync vn_invalid(vp);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync vn_free(vp);
35473cad6d5d5b57348c66f0cfdd7d51d6071ee7vboxsync LogFlowFunc((" %s vnode cleared\n", node->sf_path));
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync /*
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync * Close the sf_file for the node.
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync */
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync if (node->sf_file != NULL) {
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync (void)sfprov_close(node->sf_file);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync node->sf_file = NULL;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync }
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
f48c3167a0f99da174686b66dc4e666f38ecae46vboxsync /*
f48c3167a0f99da174686b66dc4e666f38ecae46vboxsync * Free the directory entries for the node. This should normally
f48c3167a0f99da174686b66dc4e666f38ecae46vboxsync * have been taken care of in sffs_close(), but better safe than
f48c3167a0f99da174686b66dc4e666f38ecae46vboxsync * sorry.
f48c3167a0f99da174686b66dc4e666f38ecae46vboxsync */
f48c3167a0f99da174686b66dc4e666f38ecae46vboxsync sfnode_clear_dir_list(node);
f48c3167a0f99da174686b66dc4e666f38ecae46vboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync /*
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync * If the node is stale, we can also destroy it.
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync */
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync if (node->sf_is_stale && node->sf_children == 0)
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync sfnode_destroy(node);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync mutex_exit(&sffs_lock);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync return;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync}
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync/*
1076407eab87d42ab97c61074c7d9eacd143ef0fvboxsync * All the work for this is really done in sffs_lookup().
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync */
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync/*ARGSUSED*/
1403063c7e0c0a072d59e323b66068b06278fb9avboxsyncstatic int
1403063c7e0c0a072d59e323b66068b06278fb9avboxsyncsffs_open(vnode_t **vpp, int flag, cred_t *cr, caller_context_t *ct)
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync{
838c2c5c5235354ff676aefd9bfca14373b363c0vboxsync sfnode_t *node;
838c2c5c5235354ff676aefd9bfca14373b363c0vboxsync int error = 0;
838c2c5c5235354ff676aefd9bfca14373b363c0vboxsync
838c2c5c5235354ff676aefd9bfca14373b363c0vboxsync mutex_enter(&sffs_lock);
838c2c5c5235354ff676aefd9bfca14373b363c0vboxsync
838c2c5c5235354ff676aefd9bfca14373b363c0vboxsync node = VN2SFN(*vpp);
1076407eab87d42ab97c61074c7d9eacd143ef0fvboxsync sfnode_open(node, flag);
838c2c5c5235354ff676aefd9bfca14373b363c0vboxsync if (node->sf_file == NULL)
838c2c5c5235354ff676aefd9bfca14373b363c0vboxsync error = EINVAL;
838c2c5c5235354ff676aefd9bfca14373b363c0vboxsync mutex_exit(&sffs_lock);
838c2c5c5235354ff676aefd9bfca14373b363c0vboxsync
838c2c5c5235354ff676aefd9bfca14373b363c0vboxsync return (error);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync}
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync/*
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync * All the work for this is really done in inactive.
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync */
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync/*ARGSUSED*/
1403063c7e0c0a072d59e323b66068b06278fb9avboxsyncstatic int
1403063c7e0c0a072d59e323b66068b06278fb9avboxsyncsffs_close(
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync vnode_t *vp,
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync int flag,
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync int count,
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync offset_t offset,
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync cred_t *cr,
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync caller_context_t *ct)
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync{
f48c3167a0f99da174686b66dc4e666f38ecae46vboxsync sfnode_t *node;
f48c3167a0f99da174686b66dc4e666f38ecae46vboxsync
f48c3167a0f99da174686b66dc4e666f38ecae46vboxsync mutex_enter(&sffs_lock);
f48c3167a0f99da174686b66dc4e666f38ecae46vboxsync node = VN2SFN(vp);
f48c3167a0f99da174686b66dc4e666f38ecae46vboxsync
f48c3167a0f99da174686b66dc4e666f38ecae46vboxsync /*
f48c3167a0f99da174686b66dc4e666f38ecae46vboxsync * Free the directory entries for the node. We do this on this call
f48c3167a0f99da174686b66dc4e666f38ecae46vboxsync * here because the directory node may not become inactive for a long
f48c3167a0f99da174686b66dc4e666f38ecae46vboxsync * time after the readdir is over. Case in point, if somebody cd's into
f48c3167a0f99da174686b66dc4e666f38ecae46vboxsync * the directory then it won't become inactive until they cd away again.
f48c3167a0f99da174686b66dc4e666f38ecae46vboxsync * In such a case we would end up with the directory listing not getting
f48c3167a0f99da174686b66dc4e666f38ecae46vboxsync * updated (i.e. the result of 'ls' always being the same) until they
f48c3167a0f99da174686b66dc4e666f38ecae46vboxsync * change the working directory.
f48c3167a0f99da174686b66dc4e666f38ecae46vboxsync */
f48c3167a0f99da174686b66dc4e666f38ecae46vboxsync sfnode_clear_dir_list(node);
f48c3167a0f99da174686b66dc4e666f38ecae46vboxsync
6479169ec893c18a646cec595e4e214492d180f0vboxsync sfnode_invalidate_stat_cache(node);
6479169ec893c18a646cec595e4e214492d180f0vboxsync
838c2c5c5235354ff676aefd9bfca14373b363c0vboxsync if (node->sf_file != NULL && vp->v_count <= 1)
838c2c5c5235354ff676aefd9bfca14373b363c0vboxsync {
838c2c5c5235354ff676aefd9bfca14373b363c0vboxsync (void)sfprov_close(node->sf_file);
838c2c5c5235354ff676aefd9bfca14373b363c0vboxsync node->sf_file = NULL;
838c2c5c5235354ff676aefd9bfca14373b363c0vboxsync }
838c2c5c5235354ff676aefd9bfca14373b363c0vboxsync
f48c3167a0f99da174686b66dc4e666f38ecae46vboxsync mutex_exit(&sffs_lock);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync return (0);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync}
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync/* ARGSUSED */
1403063c7e0c0a072d59e323b66068b06278fb9avboxsyncstatic int
1403063c7e0c0a072d59e323b66068b06278fb9avboxsyncsffs_seek(vnode_t *v, offset_t o, offset_t *no, caller_context_t *ct)
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync{
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync if (*no < 0 || *no > MAXOFFSET_T)
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync return (EINVAL);
16e6d031ca3d1ed4d88ae56fb94d9ad6e4d89c6bvboxsync
16e6d031ca3d1ed4d88ae56fb94d9ad6e4d89c6bvboxsync if (v->v_type == VDIR)
16e6d031ca3d1ed4d88ae56fb94d9ad6e4d89c6bvboxsync {
16e6d031ca3d1ed4d88ae56fb94d9ad6e4d89c6bvboxsync sffs_dirents_t *cur_buf = VN2SFN(v)->sf_dir_list;
16e6d031ca3d1ed4d88ae56fb94d9ad6e4d89c6bvboxsync off_t offset = 0;
16e6d031ca3d1ed4d88ae56fb94d9ad6e4d89c6bvboxsync
16e6d031ca3d1ed4d88ae56fb94d9ad6e4d89c6bvboxsync if (cur_buf == NULL)
16e6d031ca3d1ed4d88ae56fb94d9ad6e4d89c6bvboxsync return (0);
16e6d031ca3d1ed4d88ae56fb94d9ad6e4d89c6bvboxsync
16e6d031ca3d1ed4d88ae56fb94d9ad6e4d89c6bvboxsync while (cur_buf != NULL) {
16e6d031ca3d1ed4d88ae56fb94d9ad6e4d89c6bvboxsync if (*no >= offset && *no <= offset + cur_buf->sf_len)
16e6d031ca3d1ed4d88ae56fb94d9ad6e4d89c6bvboxsync return (0);
16e6d031ca3d1ed4d88ae56fb94d9ad6e4d89c6bvboxsync offset += cur_buf->sf_len;
16e6d031ca3d1ed4d88ae56fb94d9ad6e4d89c6bvboxsync cur_buf = cur_buf->sf_next;
16e6d031ca3d1ed4d88ae56fb94d9ad6e4d89c6bvboxsync }
16e6d031ca3d1ed4d88ae56fb94d9ad6e4d89c6bvboxsync return (EINVAL);
16e6d031ca3d1ed4d88ae56fb94d9ad6e4d89c6bvboxsync }
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync return (0);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync}
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync/*
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync * By returning an error for this, we prevent anything in sffs from
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync * being re-exported by NFS
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync */
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync/* ARGSUSED */
1403063c7e0c0a072d59e323b66068b06278fb9avboxsyncstatic int
1403063c7e0c0a072d59e323b66068b06278fb9avboxsyncsffs_fid(vnode_t *vp, fid_t *fidp, caller_context_t *ct)
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync{
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync return (ENOTSUP);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync}
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync/*
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync * vnode operations for regular files
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync */
1403063c7e0c0a072d59e323b66068b06278fb9avboxsyncconst fs_operation_def_t sffs_ops_template[] = {
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync#if defined(VBOX_VFS_SOLARIS_10U6)
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync VOPNAME_ACCESS, sffs_access,
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync VOPNAME_CLOSE, sffs_close,
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync VOPNAME_CREATE, sffs_create,
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync VOPNAME_FID, sffs_fid,
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync VOPNAME_FSYNC, sffs_fsync,
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync VOPNAME_GETATTR, sffs_getattr,
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync VOPNAME_INACTIVE, sffs_inactive,
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync VOPNAME_LOOKUP, sffs_lookup,
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync VOPNAME_MKDIR, sffs_mkdir,
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync VOPNAME_OPEN, sffs_open,
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync VOPNAME_PATHCONF, sffs_pathconf,
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync VOPNAME_READ, sffs_read,
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync VOPNAME_READDIR, sffs_readdir,
99eccc8f34de2d4b6af556ba2f5f0c756af237c7vboxsync VOPNAME_READLINK, sffs_readlink,
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync VOPNAME_REMOVE, sffs_remove,
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync VOPNAME_RENAME, sffs_rename,
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync VOPNAME_RMDIR, sffs_rmdir,
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync VOPNAME_SEEK, sffs_seek,
f65dabff4474710524235022d328b737f174fc1dvboxsync VOPNAME_SETATTR, sffs_setattr,
f65dabff4474710524235022d328b737f174fc1dvboxsync VOPNAME_SPACE, sffs_space,
99eccc8f34de2d4b6af556ba2f5f0c756af237c7vboxsync VOPNAME_SYMLINK, sffs_symlink,
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync VOPNAME_WRITE, sffs_write,
561b8d2b46fb10887829b7e4d7d29447817adbddvboxsync
a2907076474e923411cc5046492a88787ba377fevboxsync# ifdef VBOXVFS_WITH_MMAP
561b8d2b46fb10887829b7e4d7d29447817adbddvboxsync VOPNAME_MAP, sffs_map,
561b8d2b46fb10887829b7e4d7d29447817adbddvboxsync VOPNAME_ADDMAP, sffs_addmap,
561b8d2b46fb10887829b7e4d7d29447817adbddvboxsync VOPNAME_DELMAP, sffs_delmap,
561b8d2b46fb10887829b7e4d7d29447817adbddvboxsync VOPNAME_GETPAGE, sffs_getpage,
561b8d2b46fb10887829b7e4d7d29447817adbddvboxsync VOPNAME_PUTPAGE, sffs_putpage,
561b8d2b46fb10887829b7e4d7d29447817adbddvboxsync# endif
561b8d2b46fb10887829b7e4d7d29447817adbddvboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync NULL, NULL
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync#else
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync VOPNAME_ACCESS, { .vop_access = sffs_access },
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync VOPNAME_CLOSE, { .vop_close = sffs_close },
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync VOPNAME_CREATE, { .vop_create = sffs_create },
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync VOPNAME_FID, { .vop_fid = sffs_fid },
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync VOPNAME_FSYNC, { .vop_fsync = sffs_fsync },
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync VOPNAME_GETATTR, { .vop_getattr = sffs_getattr },
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync VOPNAME_INACTIVE, { .vop_inactive = sffs_inactive },
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync VOPNAME_LOOKUP, { .vop_lookup = sffs_lookup },
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync VOPNAME_MKDIR, { .vop_mkdir = sffs_mkdir },
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync VOPNAME_OPEN, { .vop_open = sffs_open },
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync VOPNAME_PATHCONF, { .vop_pathconf = sffs_pathconf },
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync VOPNAME_READ, { .vop_read = sffs_read },
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync VOPNAME_READDIR, { .vop_readdir = sffs_readdir },
99eccc8f34de2d4b6af556ba2f5f0c756af237c7vboxsync VOPNAME_READLINK, { .vop_readlink = sffs_readlink },
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync VOPNAME_REMOVE, { .vop_remove = sffs_remove },
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync VOPNAME_RENAME, { .vop_rename = sffs_rename },
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync VOPNAME_RMDIR, { .vop_rmdir = sffs_rmdir },
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync VOPNAME_SEEK, { .vop_seek = sffs_seek },
f65dabff4474710524235022d328b737f174fc1dvboxsync VOPNAME_SETATTR, { .vop_setattr = sffs_setattr },
f65dabff4474710524235022d328b737f174fc1dvboxsync VOPNAME_SPACE, { .vop_space = sffs_space },
99eccc8f34de2d4b6af556ba2f5f0c756af237c7vboxsync VOPNAME_SYMLINK, { .vop_symlink = sffs_symlink },
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync VOPNAME_WRITE, { .vop_write = sffs_write },
561b8d2b46fb10887829b7e4d7d29447817adbddvboxsync
a2907076474e923411cc5046492a88787ba377fevboxsync# ifdef VBOXVFS_WITH_MMAP
561b8d2b46fb10887829b7e4d7d29447817adbddvboxsync VOPNAME_MAP, { .vop_map = sffs_map },
561b8d2b46fb10887829b7e4d7d29447817adbddvboxsync VOPNAME_ADDMAP, { .vop_addmap = sffs_addmap },
561b8d2b46fb10887829b7e4d7d29447817adbddvboxsync VOPNAME_DELMAP, { .vop_delmap = sffs_delmap },
561b8d2b46fb10887829b7e4d7d29447817adbddvboxsync VOPNAME_GETPAGE, { .vop_getpage = sffs_getpage },
561b8d2b46fb10887829b7e4d7d29447817adbddvboxsync VOPNAME_PUTPAGE, { .vop_putpage = sffs_putpage },
561b8d2b46fb10887829b7e4d7d29447817adbddvboxsync# endif
561b8d2b46fb10887829b7e4d7d29447817adbddvboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync NULL, NULL
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync#endif
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync};
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync/*
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync * Also, init and fini functions...
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync */
1403063c7e0c0a072d59e323b66068b06278fb9avboxsyncint
1403063c7e0c0a072d59e323b66068b06278fb9avboxsyncsffs_vnode_init(void)
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync{
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync int err;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync err = vn_make_ops("sffs", sffs_ops_template, &sffs_ops);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync if (err)
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync return (err);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync avl_create(&sfnodes, sfnode_compare, sizeof (sfnode_t),
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync offsetof(sfnode_t, sf_linkage));
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync avl_create(&stale_sfnodes, sfnode_compare, sizeof (sfnode_t),
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync offsetof(sfnode_t, sf_linkage));
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync sffs_buffer = kmem_alloc(PAGESIZE, KM_SLEEP);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync return (0);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync}
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsyncvoid
1403063c7e0c0a072d59e323b66068b06278fb9avboxsyncsffs_vnode_fini(void)
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync{
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync if (sffs_ops)
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync vn_freevnodeops(sffs_ops);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync ASSERT(avl_first(&sfnodes) == NULL);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync avl_destroy(&sfnodes);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync if (sffs_buffer != NULL) {
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync kmem_free(sffs_buffer, PAGESIZE);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync sffs_buffer = NULL;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync }
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync}
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync/*
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync * Utility at unmount to get all nodes in that mounted filesystem removed.
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync */
1403063c7e0c0a072d59e323b66068b06278fb9avboxsyncint
1403063c7e0c0a072d59e323b66068b06278fb9avboxsyncsffs_purge(struct sffs_data *sffs)
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync{
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync sfnode_t *node;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync sfnode_t *prev;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync /*
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync * Check that no vnodes are active.
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync */
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync if (sffs->sf_rootnode->v_count > 1)
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync return (-1);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync for (node = avl_first(&sfnodes); node;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync node = AVL_NEXT(&sfnodes, node)) {
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync if (node->sf_sffs == sffs && node->sf_vnode &&
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync node->sf_vnode != sffs->sf_rootnode)
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync return (-1);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync }
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync for (node = avl_first(&stale_sfnodes); node;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync node = AVL_NEXT(&stale_sfnodes, node)) {
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync if (node->sf_sffs == sffs && node->sf_vnode &&
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync node->sf_vnode != sffs->sf_rootnode)
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync return (-1);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync }
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync /*
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync * All clear to destroy all node information. Since there are no
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync * vnodes, the make stale will cause deletion.
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync */
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync VN_RELE(sffs->sf_rootnode);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync mutex_enter(&sffs_lock);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync for (prev = NULL;;) {
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync if (prev == NULL)
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync node = avl_first(&sfnodes);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync else
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync node = AVL_NEXT(&sfnodes, prev);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync if (node == NULL)
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync break;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync if (node->sf_sffs == sffs) {
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync if (node->sf_vnode != NULL)
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync panic("vboxfs: purge hit active vnode");
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync sfnode_make_stale(node);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync } else {
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync prev = node;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync }
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync }
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync mutex_exit(&sffs_lock);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync return (0);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync}
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
561b8d2b46fb10887829b7e4d7d29447817adbddvboxsync#if 0
561b8d2b46fb10887829b7e4d7d29447817adbddvboxsync/* Debug helper functions */
1403063c7e0c0a072d59e323b66068b06278fb9avboxsyncstatic void
1403063c7e0c0a072d59e323b66068b06278fb9avboxsyncsfnode_print(sfnode_t *node)
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync{
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync Log(("0x%p", node));
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync Log((" type=%s (%d)",
4e3c02f2d10e4e96617bc4be9aebda8173279e48vboxsync node->sf_type == VDIR ? "VDIR" :
4e3c02f2d10e4e96617bc4be9aebda8173279e48vboxsync node->sf_type == VNON ? "VNON" :
99eccc8f34de2d4b6af556ba2f5f0c756af237c7vboxsync node->sf_type == VLNK ? "VLNK" :
4e3c02f2d10e4e96617bc4be9aebda8173279e48vboxsync node->sf_type == VREG ? "VREG" : "other", node->sf_type));
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync Log((" ino=%d", (uint_t)node->sf_ino));
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync Log((" path=%s", node->sf_path));
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync Log((" parent=0x%p", node->sf_parent));
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync if (node->sf_children)
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync Log((" children=%d", node->sf_children));
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync if (node->sf_vnode)
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync Log((" vnode=0x%p", node->sf_vnode));
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync Log(("%s\n", node->sf_is_stale ? " STALE" : ""));
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync}
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync
561b8d2b46fb10887829b7e4d7d29447817adbddvboxsyncstatic void
561b8d2b46fb10887829b7e4d7d29447817adbddvboxsyncsfnode_list(void)
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync{
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync sfnode_t *n;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync for (n = avl_first(&sfnodes); n != NULL; n = AVL_NEXT(&sfnodes, n))
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync sfnode_print(n);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync for (n = avl_first(&stale_sfnodes); n != NULL;
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync n = AVL_NEXT(&stale_sfnodes, n))
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync sfnode_print(n);
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync}
561b8d2b46fb10887829b7e4d7d29447817adbddvboxsync#endif
1403063c7e0c0a072d59e323b66068b06278fb9avboxsync