File: [local] / sys / xfs / xfs_vfsops-common.c (download)
Revision 1.1.1.1 (vendor branch), Tue Mar 4 16:04:30 2008 UTC (16 years, 3 months ago) by nbrk
Branch: OPENBSD_4_2_BASE, MAIN
CVS Tags: jornada-partial-support-wip, HEAD Changes since 1.1: +0 -0 lines
Import of OpenBSD 4.2 release kernel tree with initial code to support
Jornada 720/728, StrongARM 1110-based handheld PC.
At this point kernel roots on NFS and boots into vfs_mountroot() and traps.
What is supported:
- glass console, Jornada framebuffer (jfb) works in 16bpp direct color mode
(needs some palette tweaks for non black/white/blue colors, i think)
- saic, SA11x0 interrupt controller (needs cleanup)
- sacom, SA11x0 UART (supported only as boot console for now)
- SA11x0 GPIO controller fully supported (but can't handle multiple interrupt
handlers on one gpio pin)
- sassp, SSP port on SA11x0 that attaches spibus
- Jornada microcontroller (jmcu) to control kbd, battery, etc throught
the SPI bus (wskbd attaches on jmcu, but not tested)
- tod functions seem work
- initial code for SA-1111 (chip companion) : this is TODO
Next important steps, i think:
- gpio and intc on sa1111
- pcmcia support for sa11x0 (and sa1111 help logic)
- REAL root on nfs when we have PCMCIA support (we may use any of supported pccard NICs)
- root on wd0! (using already supported PCMCIA-ATA)
|
/*
* Copyright (c) 1995 - 2002 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <xfs/xfs_locl.h>
RCSID("$arla: xfs_vfsops-common.c,v 1.40 2003/06/02 18:26:40 lha Exp $");
/*
* NNPFS vfs operations.
*/
#include <xfs/xfs_common.h>
#include <xfs/xfs_message.h>
#include <xfs/xfs_fs.h>
#include <xfs/xfs_dev.h>
#include <xfs/xfs_deb.h>
#include <xfs/xfs_syscalls.h>
#include <xfs/xfs_vfsops.h>
#ifdef HAVE_KERNEL_UDEV2DEV
#define VA_RDEV_TO_DEV(x) udev2dev(x, 0) /* XXX what is the 0 */
#else
#define VA_RDEV_TO_DEV(x) x
#endif
struct xfs xfs[NNNPFS];
/*
* path and data is in system memory
*/
int
xfs_mount_common_sys(struct mount *mp,
const char *path,
void *data,
struct nameidata *ndp,
d_thread_t *p)
{
struct vnode *devvp;
dev_t dev;
int error;
struct vattr vat;
NNPFSDEB(XDEBVFOPS, ("xfs_mount: "
"struct mount mp = %lx path = '%s' data = '%s'\n",
(unsigned long)mp, path, (char *)data));
#ifdef ARLA_KNFS
NNPFSDEB(XDEBVFOPS, ("xfs_mount: mount flags = %x\n", mp->mnt_flag));
/*
* mountd(8) flushes all export entries when it starts
* right now we ignore it (but should not)
*/
if (mp->mnt_flag & MNT_UPDATE ||
mp->mnt_flag & MNT_DELEXPORT) {
NNPFSDEB(XDEBVFOPS,
("xfs_mount: ignoreing MNT_UPDATE or MNT_DELEXPORT\n"));
return 0;
}
#endif
NDINIT(ndp, LOOKUP, FOLLOW | LOCKLEAF, UIO_SYSSPACE, data, p);
error = namei(ndp);
if (error) {
NNPFSDEB(XDEBVFOPS, ("namei failed, errno = %d\n", error));
return error;
}
devvp = ndp->ni_vp;
if (devvp->v_type != VCHR) {
vput(devvp);
NNPFSDEB(XDEBVFOPS, ("not VCHR (%d)\n", devvp->v_type));
return ENXIO;
}
#if defined(__osf__)
VOP_GETATTR(devvp, &vat, ndp->ni_cred, error);
#elif defined(HAVE_FREEBSD_THREAD)
error = VOP_GETATTR(devvp, &vat, p->td_proc->p_ucred, p);
#else
error = VOP_GETATTR(devvp, &vat, p->p_ucred, p);
#endif
vput(devvp);
if (error) {
NNPFSDEB(XDEBVFOPS, ("VOP_GETATTR failed, error = %d\n", error));
return error;
}
dev = VA_RDEV_TO_DEV(vat.va_rdev);
NNPFSDEB(XDEBVFOPS, ("dev = %d.%d\n", major(dev), minor(dev)));
if (!xfs_is_xfs_dev (dev)) {
NNPFSDEB(XDEBVFOPS, ("%s is not a xfs device\n", (char *)data));
return ENXIO;
}
if (xfs[minor(dev)].status & NNPFS_MOUNTED)
return EBUSY;
xfs[minor(dev)].status = NNPFS_MOUNTED;
xfs[minor(dev)].mp = mp;
xfs[minor(dev)].root = 0;
xfs[minor(dev)].nnodes = 0;
xfs[minor(dev)].fd = minor(dev);
nnfs_init_head(&xfs[minor(dev)].nodehead);
VFS_TO_NNPFS(mp) = &xfs[minor(dev)];
#if defined(HAVE_KERNEL_VFS_GETNEWFSID)
#if defined(HAVE_TWO_ARGUMENT_VFS_GETNEWFSID)
vfs_getnewfsid(mp, MOUNT_AFS);
#else
vfs_getnewfsid(mp);
#endif /* HAVE_TWO_ARGUMENT_VFS_GETNEWFSID */
#endif /* HAVE_KERNEL_VFS_GETNEWFSID */
mp->mnt_stat.f_bsize = DEV_BSIZE;
#ifndef __osf__
mp->mnt_stat.f_iosize = DEV_BSIZE;
mp->mnt_stat.f_owner = 0;
#endif
mp->mnt_stat.f_blocks = 4711 * 4711;
mp->mnt_stat.f_bfree = 4711 * 4711;
mp->mnt_stat.f_bavail = 4711 * 4711;
mp->mnt_stat.f_files = 4711;
mp->mnt_stat.f_ffree = 4711;
mp->mnt_stat.f_flags = mp->mnt_flag;
#ifdef __osf__
mp->mnt_stat.f_fsid.val[0] = dev;
mp->mnt_stat.f_fsid.val[1] = MOUNT_NNPFS;
MALLOC(mp->m_stat.f_mntonname, char *, strlen(path) + 1,
M_PATHNAME, M_WAITOK);
strcpy(mp->m_stat.f_mntonname, path);
MALLOC(mp->m_stat.f_mntfromname, char *, sizeof("arla"),
M_PATHNAME, M_WAITOK);
strcpy(mp->m_stat.f_mntfromname, "arla");
#else /* __osf__ */
strncpy(mp->mnt_stat.f_mntonname,
path,
sizeof(mp->mnt_stat.f_mntonname));
strncpy(mp->mnt_stat.f_mntfromname,
data,
sizeof(mp->mnt_stat.f_mntfromname));
strncpy(mp->mnt_stat.f_fstypename,
"xfs",
sizeof(mp->mnt_stat.f_fstypename));
#endif /* __osf__ */
return 0;
}
int
xfs_mount_common(struct mount *mp,
const char *user_path,
void *user_data,
struct nameidata *ndp,
d_thread_t *p)
{
char *path = NULL;
char *data = NULL;
size_t count;
int error = 0;
data = malloc(MAXPATHLEN, M_TEMP, M_WAITOK);
if (data == NULL) {
error = ENOMEM;
goto done;
}
path = malloc(MAXPATHLEN, M_TEMP, M_WAITOK);
if (path == NULL) {
error = ENOMEM;
goto done;
}
error = copyinstr(user_path, path, MAXPATHLEN, &count);
if (error)
goto done;
error = copyinstr(user_data, data, MAXPATHLEN, &count);
if (error)
goto done;
error = xfs_mount_common_sys (mp, path, data, ndp, p);
done:
free(data, M_TEMP);
free(path, M_TEMP);
return(error);
}
#ifdef HAVE_KERNEL_DOFORCE
extern int doforce;
#endif
int
xfs_unmount_common(struct mount *mp, int mntflags)
{
struct xfs *xfsp = VFS_TO_NNPFS(mp);
int flags = 0;
int error;
if (mntflags & MNT_FORCE) {
#ifdef HAVE_KERNEL_DOFORCE
if (!doforce)
return EINVAL;
#endif
flags |= FORCECLOSE;
}
error = free_all_xfs_nodes(xfsp, flags, 1);
if (error)
return error;
xfsp->status = 0;
NNPFS_TO_VFS(xfsp) = NULL;
return 0;
}
int
xfs_root_common(struct mount *mp, struct vnode **vpp,
d_thread_t *proc, struct ucred *cred)
{
struct xfs *xfsp = VFS_TO_NNPFS(mp);
struct xfs_message_getroot msg;
int error;
do {
if (xfsp->root != NULL) {
*vpp = XNODE_TO_VNODE(xfsp->root);
xfs_do_vget(*vpp, LK_EXCLUSIVE, proc);
return 0;
}
msg.header.opcode = NNPFS_MSG_GETROOT;
msg.cred.uid = cred->cr_uid;
msg.cred.pag = xfs_get_pag(cred);
error = xfs_message_rpc(xfsp->fd, &msg.header, sizeof(msg), proc);
if (error == 0)
error = ((struct xfs_message_wakeup *) & msg)->error;
} while (error == 0);
/*
* Failed to get message through, need to pretend that all went well
* and return a fake dead vnode to be able to unmount.
*/
if ((error = xfs_make_dead_vnode(mp, vpp)))
return error;
NNPFS_MAKE_VROOT(*vpp);
return 0;
}