Merge from vmcontention

This commit is contained in:
attilio 2013-03-03 01:10:49 +00:00
commit a345907061
286 changed files with 929 additions and 127366 deletions

View File

@ -38,6 +38,27 @@
# xargs -n1 | sort | uniq -d;
# done
# 20130302: NTFS support removed
OLD_FILES+=usr/include/fs/ntfs/ntfs.h
OLD_FILES+=usr/include/fs/ntfs/ntfs_compr.h
OLD_FILES+=usr/include/fs/ntfs/ntfs_ihash.h
OLD_FILES+=usr/include/fs/ntfs/ntfs_inode.h
OLD_FILES+=usr/include/fs/ntfs/ntfs_subr.h
OLD_FILES+=usr/include/fs/ntfs/ntfs_vfsops.h
OLD_FILES+=usr/include/fs/ntfs/ntfsmount.h
OLD_DIRS+=usr/include/fs/ntfs
OLD_FILES+=usr/share/man/man8/mount_ntfs.8.gz
# 20130302: PORTALFS support removed
OLD_FILES+=usr/include/fs/portalfs/portal.h
OLD_DIRS+=usr/include/fs/portalfs
OLD_FILES+=usr/share/examples/portal/README
OLD_FILES+=usr/share/examples/portal/portal.conf
OLD_DIRS+=usr/share/examples/portal
OLD_FILES+=usr/share/man/man8/mount_portalfs.8.gz
# 20130302: CODAFS support removed
OLD_FILES+=usr/share/man/man4/coda.4.gz
# 20130302: XFS support removed
OLD_FILES+=usr/share/man/man5/xfs.5.gz
# 20130116: removed long unused directories for .1aout section manpages
OLD_FILES+=usr/share/man/en.ISO8859-1/man1aout
OLD_FILES+=usr/share/man/en.UTF-8/man1aout

View File

@ -568,6 +568,8 @@
43204:AUE_CAP_IOCTLS_GET:cap_ioctls_get(2):fm
43205:AUE_CAP_FCNTLS_LIMIT:cap_fcntls_limit(2):fm
43206:AUE_CAP_FCNTLS_GET:cap_fcntls_get(2):fm
43207:AUE_BINDAT:bindat(2):nt
43208:AUE_CONNECTAT:connectat(2):nt
#
# Solaris userspace events.
#

View File

@ -34,7 +34,7 @@ options {
# NB: DETACH events are ignored; the kernel should handle all cleanup
# (routes, arp cache). Beware of races against immediate create
# of a device with the same name; e.g.
# ifconfig bridge0 destroy; ifconfig bridge0 create
# ifconfig bridge0 destroy; ifconfig bridge0 create
#
notify 0 {
match "system" "IFNET";
@ -165,7 +165,7 @@ notify 100 {
};
#
# Rescan scsi device-names on attach, but not detach. However, it is
# Rescan SCSI device-names on attach, but not detach. However, it is
# disabled by default due to reports of problems.
#
attach 0 {
@ -305,13 +305,13 @@ detach 10 {
# events. See the ACPI specification for more information about
# notifies. Here is the information returned for each subsystem:
#
# ACAD: AC line state (0 is offline, 1 is online)
# Button: Button pressed (0 for power, 1 for sleep)
# CMBAT: ACPI battery events
# Lid: Lid state (0 is closed, 1 is open)
# RCTL: Resource limits
# ACAD: AC line state (0 is offline, 1 is online)
# Button: Button pressed (0 for power, 1 for sleep)
# CMBAT: ACPI battery events
# Lid: Lid state (0 is closed, 1 is open)
# RCTL: Resource limits
# Suspend, Resume: Suspend and resume notification
# Thermal: ACPI thermal zone events
# Thermal: ACPI thermal zone events
#
# This example calls a script when the AC state changes, passing the
# notify value as the first argument. If the state is 0x00, it might

View File

@ -91,6 +91,7 @@ MAN+= abort2.2 \
aio_waitcomplete.2 \
aio_write.2 \
bind.2 \
bindat.2 \
brk.2 \
cap_enter.2 \
cap_fcntls_limit.2 \
@ -105,6 +106,7 @@ MAN+= abort2.2 \
close.2 \
closefrom.2 \
connect.2 \
connectat.2 \
cpuset.2 \
cpuset_getaffinity.2 \
dup.2 \

View File

@ -378,6 +378,7 @@ FBSD_1.2 {
};
FBSD_1.3 {
bindat;
cap_fcntls_get;
cap_fcntls_limit;
cap_ioctls_get;
@ -386,6 +387,7 @@ FBSD_1.3 {
cap_rights_limit;
cap_sandboxed;
clock_getcpuclockid2;
connectat;
ffclock_getcounter;
ffclock_getestimate;
ffclock_setestimate;

109
lib/libc/sys/bindat.2 Normal file
View File

@ -0,0 +1,109 @@
.\" Copyright (c) 2013 The FreeBSD Foundation
.\" All rights reserved.
.\"
.\" This documentation was written by Pawel Jakub Dawidek under sponsorship from
.\" the FreeBSD Foundation.
.\"
.\" 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.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHORS 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 AUTHORS 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.
.\"
.\" $FreeBSD$
.\"
.Dd February 13, 2013
.Dt BINDAT 2
.Os
.Sh NAME
.Nm bindat
.Nd assign a local protocol address to a socket
.Sh LIBRARY
.Lb libc
.Sh SYNOPSIS
.In sys/types.h
.In sys/socket.h
.Pp
.In fcntl.h
.Ft int
.Fn bindat "int fd" "int s" "const struct sockaddr *addr" "socklen_t addrlen"
.Sh DESCRIPTION
The
.Fn bindat
system call assigns the local protocol address to a socket.
It works just like the
.Xr bind 2
system call with two exceptions:
.Pp
.Bl -enum -offset indent -compact
.It
It is limited to sockets in the PF_LOCAL domain.
.Pp
.It
If the file path stored in the
.Fa sun_path
field of the sockaddr_un structure is a relative path, it is located relative
to the directory associated with the file descriptor
.Fa fd .
If
.Fn bindat
is passed the special value
.Dv AT_FDCWD
in the
.Fa fd
parameter, the current working directory is used and the behavior is identical
to a call to
.Xr bind 2 .
.El
.Sh RETURN VALUES
.Rv -std bindat
.Sh ERRORS
The
.Fn bindat
system call may fail with the same errors as the
.Xr bind 2
system call for a UNIX domain socket or with the following errors:
.Bl -tag -width Er
.It Bq Er EBADF
The
.Fa sun_path
field does not specify an absolute path and the
.Fa fd
argument is neither
.Dv AT_FDCWD
nor a valid file descriptor.
.It Bq Er ENOTDIR
The
.Fa sun_path
field is not an absolute path and
.Fa fd
is neither
.Dv AT_FDCWD
nor a file descriptor associated with a directory.
.El
.Sh SEE ALSO
.Xr bind 2 ,
.Xr connectat 2 ,
.Xr socket 2 ,
.Xr unix 4
.Sh AUTHORS
The
.Nm
was developed by
.An Pawel Jakub Dawidek Aq pawel@dawidek.net
under sponsorship from the FreeBSD Foundation.

View File

@ -104,12 +104,20 @@ or
and that socket options set with
.Xr setsockopt 2
may also affect binding behavior.
.It Dv CAP_BINDAT
Permit
.Xr bindat 2 .
This right has to be present on the directory descriptor.
.It Dv CAP_CONNECT
Permit
.Xr connect 2 ;
also required for
.Xr sendto 2
with a non-NULL destination address.
.It Dv CAP_CONNECTAT
Permit
.Xr connectat 2 .
This right has to be present on the directory descriptor.
.It Dv CAP_CREATE
Permit
.Xr openat 2
@ -511,11 +519,13 @@ argument points at an invalid address.
.Xr aio_read 2 ,
.Xr aio_write 2 ,
.Xr bind 2 ,
.Xr bindat 2 ,
.Xr cap_enter 2 ,
.Xr cap_fcntls_limit 2 ,
.Xr cap_ioctls_limit 2 ,
.Xr cap_rights_limit 2 ,
.Xr connect 2 ,
.Xr connectat 2 ,
.Xr dup 2 ,
.Xr dup2 2 ,
.Xr extattr_delete_fd 2 ,

109
lib/libc/sys/connectat.2 Normal file
View File

@ -0,0 +1,109 @@
.\" Copyright (c) 2013 The FreeBSD Foundation
.\" All rights reserved.
.\"
.\" This documentation was written by Pawel Jakub Dawidek under sponsorship from
.\" the FreeBSD Foundation.
.\"
.\" 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.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHORS 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 AUTHORS 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.
.\"
.\" $FreeBSD$
.\"
.Dd February 13, 2013
.Dt CONNECTAT 2
.Os
.Sh NAME
.Nm connectat
.Nd initiate a connection on a socket
.Sh LIBRARY
.Lb libc
.Sh SYNOPSIS
.In sys/types.h
.In sys/socket.h
.Pp
.In fcntl.h
.Ft int
.Fn connectat "int fd" "int s" "const struct sockaddr *name" "socklen_t namelen"
.Sh DESCRIPTION
The
.Fn connectat
system call initiates a connection on a socket.
It works just like the
.Xr connect 2
system call with two exceptions:
.Pp
.Bl -enum -offset indent -compact
.It
It is limited to sockets in the PF_LOCAL domain.
.Pp
.It
If the file path stored in the
.Fa sun_path
field of the sockaddr_un structure is a relative path, it is located relative
to the directory associated with the file descriptor
.Fa fd .
If
.Fn connectat
is passed the special value
.Dv AT_FDCWD
in the
.Fa fd
parameter, the current working directory is used and the behavior is identical
to a call to
.Xr connect 2 .
.El
.Sh RETURN VALUES
.Rv -std connectat
.Sh ERRORS
The
.Fn connectat
system call may fail with the same errors as the
.Xr connect 2
system call for a UNIX domain socket or with the following errors:
.Bl -tag -width Er
.It Bq Er EBADF
The
.Fa sun_path
field does not specify an absolute path and the
.Fa fd
argument is neither
.Dv AT_FDCWD
nor a valid file descriptor.
.It Bq Er ENOTDIR
The
.Fa sun_path
field is not an absolute path and
.Fa fd
is neither
.Dv AT_FDCWD
nor a file descriptor associated with a directory.
.El
.Sh SEE ALSO
.Xr bindat 2 ,
.Xr connect 2 ,
.Xr socket 2 ,
.Xr unix 4
.Sh AUTHORS
The
.Nm
was developed by
.An Pawel Jakub Dawidek Aq pawel@dawidek.net
under sponsorship from the FreeBSD Foundation.

View File

@ -1,71 +0,0 @@
/*-
* Copyright (c) 2005-2009 Stanislav Sedov <stas@FreeBSD.org>
* 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.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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 <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/vnode.h>
#include <sys/mount.h>
#include <netinet/in.h>
#include <assert.h>
#include <err.h>
#include <kvm.h>
#include <stdlib.h>
#include <fs/ntfs/ntfs.h>
#include <fs/ntfs/ntfs_inode.h>
#include "libprocstat.h"
#include "common_kvm.h"
int
ntfs_filestat(kvm_t *kd, struct vnode *vp, struct vnstat *vn)
{
struct fnode fnod;
struct ntnode node;
int error;
assert(kd);
assert(vn);
error = kvm_read_all(kd, (unsigned long)VTOF(vp), &fnod, sizeof(fnod));
if (error != 0) {
warnx("can't read ntfs fnode at %p", (void *)VTOF(vp));
return (1);
}
error = kvm_read_all(kd, (unsigned long)FTONT(&fnod), &node,
sizeof(node));
if (error != 0) {
warnx("can't read ntfs node at %p", (void *)FTONT(&fnod));
return (1);
}
vn->vn_fileid = node.i_number;
vn->vn_fsid = dev2udev(kd, node.i_dev);
return (0);
}

View File

@ -3912,6 +3912,7 @@ ipfw_flush(int force)
static void table_list(uint16_t num, int need_header);
static void table_fill_xentry(char *arg, ipfw_table_xentry *xent);
/*
* This one handles all table-related commands
@ -3927,8 +3928,7 @@ ipfw_table_handler(int ac, char *av[])
int do_add;
int is_all;
size_t len;
char *p;
uint32_t a, type, mask, addrlen;
uint32_t a, mask;
uint32_t tables_max;
mask = 0; // XXX uninitialized ?
@ -3965,57 +3965,8 @@ ipfw_table_handler(int ac, char *av[])
ac--; av++;
if (!ac)
errx(EX_USAGE, "address required");
/*
* Let's try to guess type by agrument.
* Possible types:
* 1) IPv4[/mask]
* 2) IPv6[/mask]
* 3) interface name
* 4) port ?
*/
type = 0;
if (ishexnumber(*av[0])) {
/* Remove / if exists */
if ((p = strchr(*av, '/')) != NULL) {
*p = '\0';
mask = atoi(p + 1);
}
if (inet_pton(AF_INET, *av, &xent.k.addr6) == 1) {
type = IPFW_TABLE_CIDR;
if ((p != NULL) && (mask > 32))
errx(EX_DATAERR, "bad IPv4 mask width: %s", p + 1);
xent.masklen = p ? mask : 32;
addrlen = sizeof(struct in_addr);
} else if (inet_pton(AF_INET6, *av, &xent.k.addr6) == 1) {
type = IPFW_TABLE_CIDR;
if ((p != NULL) && (mask > 128))
errx(EX_DATAERR, "bad IPv6 mask width: %s", p + 1);
xent.masklen = p ? mask : 128;
addrlen = sizeof(struct in6_addr);
}
}
if ((type == 0) && (strchr(*av, '.') == NULL)) {
/* Assume interface name. Copy significant data only */
mask = MIN(strlen(*av), IF_NAMESIZE - 1);
memcpy(xent.k.iface, *av, mask);
/* Set mask to exact match */
xent.masklen = 8 * IF_NAMESIZE;
type = IPFW_TABLE_INTERFACE;
addrlen = IF_NAMESIZE;
}
if (type == 0) {
if (lookup_host(*av, (struct in_addr *)&xent.k.addr6) != 0)
errx(EX_NOHOST, "hostname ``%s'' unknown", *av);
xent.masklen = 32;
type = IPFW_TABLE_CIDR;
addrlen = sizeof(struct in_addr);
}
xent.type = type;
xent.len = offsetof(ipfw_table_xentry, k) + addrlen;
table_fill_xentry(*av, &xent);
ac--; av++;
if (do_add && ac) {
@ -4064,6 +4015,93 @@ ipfw_table_handler(int ac, char *av[])
errx(EX_USAGE, "invalid table command %s", *av);
}
static void
table_fill_xentry(char *arg, ipfw_table_xentry *xent)
{
int addrlen, mask, masklen, type;
struct in6_addr *paddr;
uint32_t *pkey;
char *p;
uint32_t key;
mask = 0;
type = 0;
addrlen = 0;
masklen = 0;
/*
* Let's try to guess type by agrument.
* Possible types:
* 1) IPv4[/mask]
* 2) IPv6[/mask]
* 3) interface name
* 4) port, uid/gid or other u32 key (base 10 format)
* 5) hostname
*/
paddr = &xent->k.addr6;
if (ishexnumber(*arg) != 0 || *arg == ':') {
/* Remove / if exists */
if ((p = strchr(arg, '/')) != NULL) {
*p = '\0';
mask = atoi(p + 1);
}
if (inet_pton(AF_INET, arg, paddr) == 1) {
if (p != NULL && mask > 32)
errx(EX_DATAERR, "bad IPv4 mask width: %s",
p + 1);
type = IPFW_TABLE_CIDR;
masklen = p ? mask : 32;
addrlen = sizeof(struct in_addr);
} else if (inet_pton(AF_INET6, arg, paddr) == 1) {
if (IN6_IS_ADDR_V4COMPAT(paddr))
errx(EX_DATAERR,
"Use IPv4 instead of v4-compatible");
if (p != NULL && mask > 128)
errx(EX_DATAERR, "bad IPv6 mask width: %s",
p + 1);
type = IPFW_TABLE_CIDR;
masklen = p ? mask : 128;
addrlen = sizeof(struct in6_addr);
} else {
/* Port or any other key */
key = strtol(arg, &p, 10);
/* Skip non-base 10 entries like 'fa1' */
if (p != arg) {
pkey = (uint32_t *)paddr;
*pkey = htonl(key);
type = IPFW_TABLE_CIDR;
addrlen = sizeof(uint32_t);
}
}
}
if (type == 0 && strchr(arg, '.') == NULL) {
/* Assume interface name. Copy significant data only */
mask = MIN(strlen(arg), IF_NAMESIZE - 1);
memcpy(xent->k.iface, arg, mask);
/* Set mask to exact match */
masklen = 8 * IF_NAMESIZE;
type = IPFW_TABLE_INTERFACE;
addrlen = IF_NAMESIZE;
}
if (type == 0) {
if (lookup_host(arg, (struct in_addr *)paddr) != 0)
errx(EX_NOHOST, "hostname ``%s'' unknown", arg);
masklen = 32;
type = IPFW_TABLE_CIDR;
addrlen = sizeof(struct in_addr);
}
xent->type = type;
xent->masklen = masklen;
xent->len = offsetof(ipfw_table_xentry, k) + addrlen;
}
static void
table_list(uint16_t num, int need_header)
{
@ -4107,8 +4145,8 @@ table_list(uint16_t num, int need_header)
tval = xent->value;
addr6 = &xent->k.addr6;
if ((addr6->s6_addr32[0] == 0) && (addr6->s6_addr32[1] == 0) &&
(addr6->s6_addr32[2] == 0)) {
if (IN6_IS_ADDR_V4COMPAT(addr6)) {
/* IPv4 address */
inet_ntop(AF_INET, &addr6->s6_addr32[3], tbuf, sizeof(tbuf));
} else {

View File

@ -1,14 +0,0 @@
#
# $FreeBSD$
#
PROG= mount_hpfs
SRCS= mount_hpfs.c getmntopts.c
MAN= mount_hpfs.8
MOUNT= ${.CURDIR}/../mount
CFLAGS+= -I${MOUNT} -DHPFS
.PATH: ${MOUNT}
.include <bsd.prog.mk>

View File

@ -1,100 +0,0 @@
.\"
.\" Copyright (c) 1993,1994 Christopher G. Demetriou
.\" Copyright (c) 1999 Semen Ustimenko <semenu@FreeBSD.org>
.\" 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. All advertising materials mentioning features or use of this software
.\" must display the following acknowledgment:
.\" This product includes software developed by Christopher G. Demetriou.
.\" 3. The name of the author may not be used to endorse or promote products
.\" derived from this software without specific prior written permission
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
.\"
.\" $FreeBSD$
.\"
.Dd May 20, 1999
.Dt MOUNT_HPFS 8
.Os
.Sh NAME
.Nm mount_hpfs
.Nd mount an HPFS file system
.Sh SYNOPSIS
.Nm
.Op Fl o Ar options
.Op Fl u Ar uid
.Op Fl g Ar gid
.Op Fl m Ar mask
.Pa special
.Pa node
.Sh DESCRIPTION
The
.Nm
utility attaches the HPFS file system residing on the device
.Pa special
to the global file system namespace at the location
indicated by
.Pa node .
This command is normally executed by
.Xr mount 8
at boot time, but can be used by any user to mount an
HPFS file system on any directory that they own (provided,
of course, that they have appropriate access to the device that
contains the file system).
.Pp
The options are as follows:
.Bl -tag -width Ds
.It Fl u Ar uid
Set the owner of the files in the file system to
.Ar uid .
The default owner is the owner of the directory
on which the file system is being mounted.
.It Fl g Ar gid
Set the group of the files in the file system to
.Ar gid .
The default group is the group of the directory
on which the file system is being mounted.
.It Fl m Ar mask
Specify the maximum file permissions for files
in the file system.
.El
.Sh EXAMPLES
To mount an hpfs volume located in /dev/wd1s1:
.Bd -literal -offset indent
# mount_hpfs /dev/wd1s1 /mnt
.Ed
.Sh WRITING
There is limited writing ability and it is not well-tested.
It is strongly recommended to mount readonly!
.Sh SEE ALSO
.Xr mount 2 ,
.Xr unmount 2 ,
.Xr fstab 5 ,
.Xr mount 8
.Sh HISTORY
The
.Nm
utility first appeared in
.Fx 3.0 .
.Sh AUTHORS
HPFS kernel implementation,
.Nm
and manual were written by
.An Semen Ustimenko Aq semenu@FreeBSD.org .

View File

@ -1,244 +0,0 @@
/*
* Copyright (c) 1994 Christopher G. Demetriou
* Copyright (c) 1999 Semen Ustimenko (semenu@FreeBSD.org)
* 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. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by Christopher G. Demetriou.
* 4. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
*
* $FreeBSD$
*/
#include <sys/cdefs.h>
#include <sys/param.h>
#include <sys/mount.h>
#include <sys/stat.h>
#include <fs/hpfs/hpfsmount.h>
#include <ctype.h>
#include <err.h>
#include <grp.h>
#include <pwd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sysexits.h>
#include <unistd.h>
#include "mntopts.h"
static struct mntopt mopts[] = {
MOPT_STDOPTS,
MOPT_END
};
static gid_t a_gid(char *);
static uid_t a_uid(char *);
static mode_t a_mask(char *);
static void usage(void) __dead2;
static void load_u2wtable(struct hpfs_args *, char *);
int
main(int argc, char *argv[])
{
struct hpfs_args args;
struct stat sb;
int c, mntflags, set_gid, set_uid, set_mask;
int forcerw = 0;
char *dev, *dir, ndir[MAXPATHLEN];
mntflags = set_gid = set_uid = set_mask = 0;
(void)memset(&args, '\0', sizeof(args));
while ((c = getopt(argc, argv, "u:g:m:o:c:W:F")) != -1) {
switch (c) {
case 'F':
forcerw=1;
break;
case 'u':
args.uid = a_uid(optarg);
set_uid = 1;
break;
case 'g':
args.gid = a_gid(optarg);
set_gid = 1;
break;
case 'm':
args.mode = a_mask(optarg);
set_mask = 1;
break;
case 'o':
getmntopts(optarg, mopts, &mntflags, 0);
break;
case 'W':
load_u2wtable(&args, optarg);
args.flags |= HPFSMNT_TABLES;
break;
case '?':
default:
usage();
break;
}
}
if (optind + 2 != argc)
usage();
if (!(mntflags & MNT_RDONLY) && !forcerw) {
warnx("Write support is BETA, you need -F flag to enable RW mount!");
exit (111);
}
dev = argv[optind];
dir = argv[optind + 1];
if (dir[0] != '/') {
warnx("\"%s\" is a relative path", dir);
if (getcwd(ndir, sizeof(ndir)) == NULL)
err(EX_OSERR, "getcwd");
strncat(ndir, "/", sizeof(ndir) - strlen(ndir) - 1);
strncat(ndir, dir, sizeof(ndir) - strlen(ndir) - 1);
dir = ndir;
warnx("using \"%s\" instead", dir);
}
args.fspec = dev;
args.export.ex_root = 65534; /* unchecked anyway on DOS fs */
if (mntflags & MNT_RDONLY)
args.export.ex_flags = MNT_EXRDONLY;
else
args.export.ex_flags = 0;
if (!set_gid || !set_uid || !set_mask) {
if (stat(dir, &sb) == -1)
err(EX_OSERR, "stat %s", dir);
if (!set_uid)
args.uid = sb.st_uid;
if (!set_gid)
args.gid = sb.st_gid;
if (!set_mask)
args.mode = sb.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO);
}
if (mount("hpfs", dir, mntflags, &args) < 0)
err(EX_OSERR, "%s", dev);
exit (0);
}
gid_t
a_gid(char *s)
{
struct group *gr;
char *gname;
gid_t gid;
if ((gr = getgrnam(s)) != NULL)
gid = gr->gr_gid;
else {
for (gname = s; *s && isdigit(*s); ++s);
if (!*s)
gid = atoi(gname);
else
errx(EX_NOUSER, "unknown group id: %s", gname);
}
return (gid);
}
uid_t
a_uid(char *s)
{
struct passwd *pw;
char *uname;
uid_t uid;
if ((pw = getpwnam(s)) != NULL)
uid = pw->pw_uid;
else {
for (uname = s; *s && isdigit(*s); ++s);
if (!*s)
uid = atoi(uname);
else
errx(EX_NOUSER, "unknown user id: %s", uname);
}
return (uid);
}
mode_t
a_mask(char *s)
{
int done, rv=0;
char *ep;
done = 0;
if (*s >= '0' && *s <= '7') {
done = 1;
rv = strtol(optarg, &ep, 8);
}
if (!done || rv < 0 || *ep)
errx(EX_USAGE, "invalid file mode: %s", s);
return (rv);
}
void
usage(void)
{
fprintf(stderr, "usage: mount_hpfs [-u user] [-g group] [-m mask] bdev dir\n");
exit(EX_USAGE);
}
void
load_u2wtable (struct hpfs_args *pargs, char *name)
{
FILE *f;
int i, code;
char buf[128];
char *fn;
if (*name == '/')
fn = name;
else {
snprintf(buf, sizeof(buf), "/usr/libdata/msdosfs/%s", name);
buf[127] = '\0';
fn = buf;
}
if ((f = fopen(fn, "r")) == NULL)
err(EX_NOINPUT, "%s", fn);
for (i = 0; i < 128; i++) {
if (fscanf(f, "%i", &code) != 1)
errx(EX_DATAERR, "u2w: missing item number %d", i);
/* pargs->u2w[i] = code; */
}
for (i = 0; i < 128; i++) {
if (fscanf(f, "%i", &code) != 1)
errx(EX_DATAERR, "d2u: missing item number %d", i);
pargs->d2u[i] = code;
}
for (i = 0; i < 128; i++) {
if (fscanf(f, "%i", &code) != 1)
errx(EX_DATAERR, "u2d: missing item number %d", i);
pargs->u2d[i] = code;
}
fclose(f);
}

View File

@ -1,20 +0,0 @@
#
# $FreeBSD$
#
PROG= mount_ntfs
SRCS= mount_ntfs.c getmntopts.c
MAN= mount_ntfs.8
DPADD= ${LIBKICONV}
LDADD= -lkiconv
MOUNT= ${.CURDIR}/../mount
CFLAGS+= -I${MOUNT}
# Needs to be dynamically linked for optional dlopen() access to
# userland libiconv
NO_SHARED?= NO
.PATH: ${MOUNT}
.include <bsd.prog.mk>

View File

@ -1,173 +0,0 @@
.\"
.\" Copyright (c) 1993,1994 Christopher G. Demetriou
.\" Copyright (c) 1999 Semen Ustimenko
.\" 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. All advertising materials mentioning features or use of this software
.\" must display the following acknowledgment:
.\" This product includes software developed by Christopher G. Demetriou.
.\" 3. The name of the author may not be used to endorse or promote products
.\" derived from this software without specific prior written permission
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
.\"
.\" $FreeBSD$
.\"
.Dd November 17, 2007
.Dt MOUNT_NTFS 8
.Os
.Sh NAME
.Nm mount_ntfs
.Nd mount an NTFS file system
.Sh SYNOPSIS
.Nm
.Op Fl a
.Op Fl i
.Op Fl u Ar user
.Op Fl g Ar group
.Op Fl m Ar mask
.Op Fl C Ar charset
.Op Fl W Ar u2wtable
.Pa special
.Pa node
.Sh DESCRIPTION
The
.Nm
utility attaches the NTFS file system residing on the device
.Pa special
to the global file system namespace at the location
indicated by
.Pa node .
This command is normally executed by
.Xr mount 8
at boot time, but can be used by any user to mount an
NTFS file system on any directory that they own (provided,
of course, that they have appropriate access to the device that
contains the file system).
.Pp
The options are as follows:
.Bl -tag -width Ds
.It Fl a
Force behaviour to return MS-DOS 8.3 names also on
.Fn readdir .
.It Fl i
Make name lookup case insensitive for all names except POSIX names.
.It Fl u Ar user
Set the owner of the files in the file system to
.Ar user .
The default owner is the owner of the directory
on which the file system is being mounted.
.It Fl g Ar group
Set the group of the files in the file system to
.Ar group .
The default group is the group of the directory
on which the file system is being mounted.
.It Fl m Ar mask
Specify the maximum file permissions for files
in the file system.
Only the nine low-order bits of
.Ar mask
are used.
.It Fl C Ar charset
Specify local
.Ar charset
to convert Unicode file names.
Currently only reading is supported, thus the file system is to be
mounted read-only.
.It Fl W Ar u2wtable
Specify
.Ux
to
.Tn Unicode
translation table.
See
.Xr mount_msdosfs 8
for the description of this option.
.Bf Em
This option is preserved for backward compatibility purpose only,
and will be removed in the future.
Please do not use this option.
.Ef
.El
.Sh FEATURES
NTFS file attributes are accessed in following way:
.Bd -literal -offset indent
foo[[:ATTRTYPE]:ATTRNAME]
.Ed
.Pp
.Sq ATTRTYPE
is one of the identifiers listed in $AttrDef file of
volume.
Default is $DATA.
.Sq ATTRNAME
is an attribute name.
Default is none.
.Sh EXAMPLES
To mount an NTFS volume located in
.Pa /dev/ad1s1 :
.Pp
.Dl "mount_ntfs /dev/ad1s1 /mnt"
.Pp
To get the volume name (in Unicode):
.Pp
.Dl "cat /mnt/\e$Volume:\e$VOLUME_NAME"
.Pp
To read directory raw data:
.Pp
.Dl "cat /mnt/foodir:\e$INDEX_ROOT:\e$I30"
.Pp
To mount a Japanese NTFS volume located in
.Pa /dev/ad0s1 :
.Pp
.Dl "mount_ntfs -C eucJP /dev/ad0s1 /mnt"
.Sh WRITING
There is limited writing ability.
Limitations: file must be nonresident
and must not contain any sparces (uninitialized areas); compressed
files are also not supported.
The file name must not contain multibyte characters.
.Sh SEE ALSO
.Xr mount 2 ,
.Xr unmount 2 ,
.Xr fstab 5 ,
.Xr mount 8 ,
.Xr mount_msdosfs 8
.Sh HISTORY
The
.Nm
utility first appeared in
.Fx 3.0 .
.Pp
The Unicode conversion routine was added by
.An Ryuichiro Imura Aq imura@ryu16.org
in 2003.
.Sh AUTHORS
The NTFS kernel implementation,
.Nm
utility, and manual were written by
.An Semen Ustimenko Aq semenu@FreeBSD.org .
.Sh CAVEATS
This utility is primarily used for read access to an NTFS volume.
See the
.Sx WRITING
section for details about writing to an NTFS volume.
.Pp
For a full read-write NTFS support consider sysutils/fusefs-ntfs
port/package.

View File

@ -1,280 +0,0 @@
/*
* Copyright (c) 1994 Christopher G. Demetriou
* Copyright (c) 1999 Semen Ustimenko
* 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. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by Christopher G. Demetriou.
* 4. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
*
* $FreeBSD$
*
*/
#include <sys/cdefs.h>
#include <sys/param.h>
#define NTFS
#include <sys/mount.h>
#include <sys/stat.h>
#include <sys/module.h>
#include <sys/iconv.h>
#include <sys/linker.h>
#include <fs/ntfs/ntfsmount.h>
#include <ctype.h>
#include <err.h>
#include <grp.h>
#include <pwd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sysexits.h>
#include <unistd.h>
#include <libutil.h>
#include "mntopts.h"
#define TRANSITION_PERIOD_HACK
static struct mntopt mopts[] = {
MOPT_STDOPTS,
MOPT_END
};
static gid_t a_gid(char *);
static uid_t a_uid(char *);
static mode_t a_mask(char *);
static void usage(void) __dead2;
static int set_charset(struct ntfs_args *);
int
main(int argc, char *argv[])
{
struct ntfs_args args;
struct stat sb;
int c, mntflags, set_gid, set_uid, set_mask;
char *dev, *dir, mntpath[MAXPATHLEN];
mntflags = set_gid = set_uid = set_mask = 0;
(void)memset(&args, '\0', sizeof(args));
args.cs_ntfs = NULL;
args.cs_local = NULL;
#ifdef TRANSITION_PERIOD_HACK
while ((c = getopt(argc, argv, "aiu:g:m:o:C:W:")) != -1) {
#else
while ((c = getopt(argc, argv, "aiu:g:m:o:C:")) != -1) {
#endif
switch (c) {
case 'u':
args.uid = a_uid(optarg);
set_uid = 1;
break;
case 'g':
args.gid = a_gid(optarg);
set_gid = 1;
break;
case 'm':
args.mode = a_mask(optarg);
set_mask = 1;
break;
case 'i':
args.flag |= NTFS_MFLAG_CASEINS;
break;
case 'a':
args.flag |= NTFS_MFLAG_ALLNAMES;
break;
case 'o':
getmntopts(optarg, mopts, &mntflags, 0);
break;
case 'C':
args.cs_local = malloc(ICONV_CSNMAXLEN);
if (args.cs_local == NULL)
err(EX_OSERR, "malloc()");
strncpy(args.cs_local,
kiconv_quirkcs(optarg, KICONV_VENDOR_MICSFT),
ICONV_CSNMAXLEN);
break;
#ifdef TRANSITION_PERIOD_HACK
case 'W':
args.cs_local = malloc(ICONV_CSNMAXLEN);
if (args.cs_local == NULL)
err(EX_OSERR, "malloc()");
if (strcmp(optarg, "iso22dos") == 0) {
strcpy(args.cs_local, "ISO8859-2");
} else if (strcmp(optarg, "iso72dos") == 0) {
strcpy(args.cs_local, "ISO8859-7");
} else if (strcmp(optarg, "koi2dos") == 0) {
strcpy(args.cs_local, "KOI8-R");
} else if (strcmp(optarg, "koi8u2dos") == 0) {
strcpy(args.cs_local, "KOI8-U");
} else {
err(EX_NOINPUT, "%s", optarg);
}
break;
#endif /* TRANSITION_PERIOD_HACK */
case '?':
default:
usage();
break;
}
}
if (optind + 2 != argc)
usage();
dev = argv[optind];
dir = argv[optind + 1];
if (args.cs_local) {
if (set_charset(&args) == -1)
err(EX_OSERR, "ntfs_iconv");
args.flag |= NTFS_MFLAG_KICONV;
/*
* XXX
* Force to be MNT_RDONLY,
* since only reading is supported right now,
*/
mntflags |= MNT_RDONLY;
}
/*
* Resolve the mountpoint with realpath(3) and remove unnecessary
* slashes from the devicename if there are any.
*/
if (checkpath(dir, mntpath) != 0)
err(EX_USAGE, "%s", mntpath);
(void)rmslashes(dev, dev);
args.fspec = dev;
args.export.ex_root = 65534; /* unchecked anyway on DOS fs */
if (mntflags & MNT_RDONLY)
args.export.ex_flags = MNT_EXRDONLY;
else
args.export.ex_flags = 0;
if (!set_gid || !set_uid || !set_mask) {
if (stat(mntpath, &sb) == -1)
err(EX_OSERR, "stat %s", mntpath);
if (!set_uid)
args.uid = sb.st_uid;
if (!set_gid)
args.gid = sb.st_gid;
if (!set_mask)
args.mode = sb.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO);
}
if (mount("ntfs", mntpath, mntflags, &args) < 0)
err(EX_OSERR, "%s", dev);
exit (0);
}
gid_t
a_gid(char *s)
{
struct group *gr;
char *gname;
gid_t gid;
if ((gr = getgrnam(s)) != NULL)
gid = gr->gr_gid;
else {
for (gname = s; *s && isdigit(*s); ++s);
if (!*s)
gid = atoi(gname);
else
errx(EX_NOUSER, "unknown group id: %s", gname);
}
return (gid);
}
uid_t
a_uid(char *s)
{
struct passwd *pw;
char *uname;
uid_t uid;
if ((pw = getpwnam(s)) != NULL)
uid = pw->pw_uid;
else {
for (uname = s; *s && isdigit(*s); ++s);
if (!*s)
uid = atoi(uname);
else
errx(EX_NOUSER, "unknown user id: %s", uname);
}
return (uid);
}
mode_t
a_mask(char *s)
{
int done, rv=0;
char *ep;
done = 0;
if (*s >= '0' && *s <= '7') {
done = 1;
rv = strtol(optarg, &ep, 8);
}
if (!done || rv < 0 || *ep)
errx(EX_USAGE, "invalid file mode: %s", s);
return (rv);
}
void
usage(void)
{
#ifdef TRANSITION_PERIOD_HACK
fprintf(stderr, "%s\n%s\n",
"usage: mount_ntfs [-a] [-i] [-u user] [-g group] [-m mask]",
" [-C charset] [-W u2wtable] special node");
#else
fprintf(stderr, "usage: mount_ntfs [-a] [-i] [-u user] [-g group] [-m mask] [-C charset] special node\n");
#endif
exit(EX_USAGE);
}
int
set_charset(struct ntfs_args *pargs)
{
int error;
if (modfind("ntfs_iconv") < 0)
if (kldload("ntfs_iconv") < 0 || modfind("ntfs_iconv") < 0) {
warnx( "cannot find or load \"ntfs_iconv\" kernel module");
return (-1);
}
if ((pargs->cs_ntfs = malloc(ICONV_CSNMAXLEN)) == NULL)
return (-1);
strncpy(pargs->cs_ntfs, ENCODING_UNICODE, ICONV_CSNMAXLEN);
error = kiconv_add_xlat16_cspairs(pargs->cs_ntfs, pargs->cs_local);
if (error)
return (-1);
return (0);
}

View File

@ -1,65 +0,0 @@
$FreeBSD$
This contains a couple of examples for using the portal filing system.
The portal file system provides a way of obtaining a file descriptor
to a filesystem object (i.e. something that is accessed by open(2),
pipe(2), socket(2) or socketpair(2)) via the filesystem namespace.
At present the only file descriptor supported are TCP sockets and
files.
NOTE!!!! The portal file system is experimental in nature and should
not be considered secure, use with caution.
First off mount the filesystem using something like:
# mount_portalfs /usr/share/examples/portal/portal.conf /p
Then you should be able to do things like
# cat /p/tcp/localhost/daytime
Sun Nov 22 17:50:09 1998
(assuming inetd is running the daytime service, by default it is off)
Welcome to FreeBSD!
# mkdir -p /tmp/root
# cd /tmp/root
# mkdir bin p
# cp /bin/sh /bin/cat bin
# mount_portalfs /usr/share/examples/portal/portal.conf /tmp/root/p
# chroot /tmp/root
# pwd
/
# echo *
bin p
# cat /etc/motd
cat: /etc/motd: No such file or directory
# cat /p/fs/etc/motd
FreeBSD 2.2.6-RELEASE (COMPUTER) #0: Sat Aug 22 17:11:37 BST 1998
Welcome to FreeBSD!
Finally, a very simple example of the listening server is available,
fire up two xterms. In the first
xterm-1$ cat /p/tcplisten/ANY/6666
(the ANY is a wildcard just like using INADDR_ANY, any resolvable host
can be used).
In the second xterm
xterm-2$ echo "hello there" >/p/tcp/localhost/6666
You should see the "hello there" string appear on the first terminal.
Unprivilged users can't create servers on privalged ports.
xterm-1$ cat /p/tcplisten/ANY/666
cat: /p/tcplisten/ANY/666: Operation not permitted
but root can
xterm-1# cat /p/tcplisten/ANY/666
In the second
xterm-2$ echo "hello there" >/p/tcp/localhost/666
should produce the expected response.
You can also swap the client/server read and write commands etc.

View File

@ -1,3 +0,0 @@
tcp/ tcp tcp/
tcplisten/ tcplisten tcplisten/
fs/ file fs/

View File

@ -1,82 +0,0 @@
.\" Copyright (c) 2008 Robert N. M. Watson
.\" 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.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHORS 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 AUTHORS 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.
.\"
.\" $FreeBSD$
.\"
.Dd January 21, 2008
.Dt CODA 4
.Os
.Sh NAME
.Nm coda
.Nd Coda Distributed File System
.Sh SYNOPSIS
To compile this driver into the kernel,
place the following lines in your
kernel configuration file:
.Bd -ragged -offset indent
.Cd "options CODA"
.Ed
.Pp
Alternatively, to load the driver as a
module at boot time, place the following line in
.Xr loader.conf 5 :
.Bd -literal -offset indent
coda_load="YES"
.Ed
.Pp
To load as a kernel loadable module after boot:
.Pp
.Dl "kldload coda"
.Sh DESCRIPTION
The
.Nm
kernel module allows the experimental, third-party Coda distributed file
system client to be used with
.Fx .
The module allows the userspace Coda client daemon, Venus, to present the
Coda distributed file system namespace via the local
.Pa /coda
file system mountpoint via the
.Pa /dev/cfs0
special device.
.Pp
To use Coda, the Coda client software package must also be installed; more
information on Coda may be found in the Coda documentation distributed with
that package.
.Sh SEE ALSO
.Xr loader.conf 5 ,
.Xr kldload 8
.Sh HISTORY
Support for
.Nm
first appeared in
.Fx 3.0 .
.Sh AUTHORS
This manual page was written by
.An Robert Watson Aq rwatson@FreeBSD.org .
.Sh BUGS
The
Coda distributed file system is considered experimental, and production
deployment should occur only after careful consideration of the risks of
deploying experimental software.

View File

@ -1,108 +0,0 @@
.\"
.\" Copyright (c) 2007 Craig Rodrigues
.\" 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.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
.\"
.\" $FreeBSD$
.\"
.Dd January 16, 2011
.Dt XFS 5
.Os
.Sh NAME
.Nm xfs
.Nd "XFS file system"
.Sh SYNOPSIS
To link into the kernel:
.Bd -ragged -offset indent
.Cd "options XFS"
.Ed
.Pp
To load as a kernel loadable module:
.Pp
.Dl "kldload xfs"
.Sh DESCRIPTION
The
.Nm
driver will permit the
.Fx
kernel to access
.Tn XFS
file systems.
.Sh EXAMPLES
To mount a
.Nm
volume located on
.Pa /dev/ad1s1 :
.Pp
.Dl "mount -t xfs -o ro /dev/ad1s1 /mnt"
.Sh SEE ALSO
.Xr nmount 2 ,
.Xr unmount 2 ,
.Xr fstab 5 ,
.Xr mount 8
.Sh NOTES
The
.Pa sysutils/xfsprogs
port contains the
.Cm mkfs.xfs
utility for
creating XFS file systems, and also other utilities for analyzing,
and repairing XFS file systems.
.Sh HISTORY
XFS was originally written by SGI for the IRIX operating system.
SGI ported XFS to Linux, and released the source code under the GNU
Public License. For more details, see:
.Pa http://oss.sgi.com/projects/xfs
.Pp
The port to
.Fx
was based on the Linux port, and started by
.An -nosplit
.An Russell Cattelan Aq cattelan@xfs.org ,
.An Alexander Kabaev Aq kan@FreeBSD.org ,
and
.An Craig Rodrigues Aq rodrigc@FreeBSD.org .
.Pp
The
.Nm
file system support
first appeared in
.Fx 7.0 .
.Sh AUTHORS
This manual page was written by
.An Craig Rodrigues Aq rodrigc@FreeBSD.org .
.Sh CAVEATS
The port of XFS to
.Fx
is currently incomplete.
Only read-only access is supported for XFS volumes.
Writing to a volume is not supported.
.Pp
The
.Fl p
flag to
.Cm mkfs.xfs
can be used to create an XFS file system which is populated with files
and other metadata.
This can be used to quickly create a read-only file system which
can be tested on
.Fx .

View File

@ -608,6 +608,8 @@
#define AUE_CAP_IOCTLS_GET 43204 /* TrustedBSD. */
#define AUE_CAP_FCNTLS_LIMIT 43205 /* TrustedBSD. */
#define AUE_CAP_FCNTLS_GET 43206 /* TrustedBSD. */
#define AUE_BINDAT 43207 /* TrustedBSD. */
#define AUE_CONNECTAT 43208 /* TrustedBSD. */
/*
* Darwin BSM uses a number of AUE_O_* definitions, which are aliased to the

View File

@ -3,7 +3,7 @@
*
* DO NOT EDIT-- this file is automatically generated.
* $FreeBSD$
* created from FreeBSD: head/sys/compat/freebsd32/syscalls.master 247602 2013-03-02 00:53:12Z pjd
* created from FreeBSD: head/sys/compat/freebsd32/syscalls.master 247667 2013-03-02 21:11:30Z pjd
*/
#ifndef _FREEBSD32_SYSPROTO_H_

View File

@ -3,7 +3,7 @@
*
* DO NOT EDIT-- this file is automatically generated.
* $FreeBSD$
* created from FreeBSD: head/sys/compat/freebsd32/syscalls.master 247602 2013-03-02 00:53:12Z pjd
* created from FreeBSD: head/sys/compat/freebsd32/syscalls.master 247667 2013-03-02 21:11:30Z pjd
*/
#define FREEBSD32_SYS_syscall 0
@ -435,4 +435,6 @@
#define FREEBSD32_SYS_cap_ioctls_get 535
#define FREEBSD32_SYS_cap_fcntls_limit 536
#define FREEBSD32_SYS_cap_fcntls_get 537
#define FREEBSD32_SYS_MAXSYSCALL 538
#define FREEBSD32_SYS_bindat 538
#define FREEBSD32_SYS_connectat 539
#define FREEBSD32_SYS_MAXSYSCALL 540

View File

@ -3,7 +3,7 @@
*
* DO NOT EDIT-- this file is automatically generated.
* $FreeBSD$
* created from FreeBSD: head/sys/compat/freebsd32/syscalls.master 247602 2013-03-02 00:53:12Z pjd
* created from FreeBSD: head/sys/compat/freebsd32/syscalls.master 247667 2013-03-02 21:11:30Z pjd
*/
const char *freebsd32_syscallnames[] = {
@ -561,4 +561,6 @@ const char *freebsd32_syscallnames[] = {
"cap_ioctls_get", /* 535 = cap_ioctls_get */
"cap_fcntls_limit", /* 536 = cap_fcntls_limit */
"cap_fcntls_get", /* 537 = cap_fcntls_get */
"bindat", /* 538 = bindat */
"connectat", /* 539 = connectat */
};

View File

@ -3,7 +3,7 @@
*
* DO NOT EDIT-- this file is automatically generated.
* $FreeBSD$
* created from FreeBSD: head/sys/compat/freebsd32/syscalls.master 247602 2013-03-02 00:53:12Z pjd
* created from FreeBSD: head/sys/compat/freebsd32/syscalls.master 247667 2013-03-02 21:11:30Z pjd
*/
#include "opt_compat.h"
@ -598,4 +598,6 @@ struct sysent freebsd32_sysent[] = {
{ AS(cap_ioctls_get_args), (sy_call_t *)sys_cap_ioctls_get, AUE_CAP_IOCTLS_GET, NULL, 0, 0, 0, SY_THR_STATIC }, /* 535 = cap_ioctls_get */
{ AS(cap_fcntls_limit_args), (sy_call_t *)sys_cap_fcntls_limit, AUE_CAP_FCNTLS_LIMIT, NULL, 0, 0, 0, SY_THR_STATIC }, /* 536 = cap_fcntls_limit */
{ AS(cap_fcntls_get_args), (sy_call_t *)sys_cap_fcntls_get, AUE_CAP_FCNTLS_GET, NULL, 0, 0, 0, SY_THR_STATIC }, /* 537 = cap_fcntls_get */
{ AS(bindat_args), (sy_call_t *)sys_bindat, AUE_BINDAT, NULL, 0, 0, 0, SY_THR_STATIC }, /* 538 = bindat */
{ AS(connectat_args), (sy_call_t *)sys_connectat, AUE_CONNECTAT, NULL, 0, 0, 0, SY_THR_STATIC }, /* 539 = connectat */
};

View File

@ -3130,6 +3130,26 @@ systrace_args(int sysnum, void *params, uint64_t *uarg, int *n_args)
*n_args = 2;
break;
}
/* bindat */
case 538: {
struct bindat_args *p = params;
iarg[0] = p->fd; /* int */
iarg[1] = p->s; /* int */
uarg[2] = (intptr_t) p->name; /* caddr_t */
iarg[3] = p->namelen; /* int */
*n_args = 4;
break;
}
/* connectat */
case 539: {
struct connectat_args *p = params;
iarg[0] = p->fd; /* int */
iarg[1] = p->s; /* int */
uarg[2] = (intptr_t) p->name; /* caddr_t */
iarg[3] = p->namelen; /* int */
*n_args = 4;
break;
}
default:
*n_args = 0;
break;
@ -8356,6 +8376,44 @@ systrace_entry_setargdesc(int sysnum, int ndx, char *desc, size_t descsz)
break;
};
break;
/* bindat */
case 538:
switch(ndx) {
case 0:
p = "int";
break;
case 1:
p = "int";
break;
case 2:
p = "caddr_t";
break;
case 3:
p = "int";
break;
default:
break;
};
break;
/* connectat */
case 539:
switch(ndx) {
case 0:
p = "int";
break;
case 1:
p = "int";
break;
case 2:
p = "caddr_t";
break;
case 3:
p = "int";
break;
default:
break;
};
break;
default:
break;
};
@ -10143,6 +10201,16 @@ systrace_return_setargdesc(int sysnum, int ndx, char *desc, size_t descsz)
if (ndx == 0 || ndx == 1)
p = "int";
break;
/* bindat */
case 538:
if (ndx == 0 || ndx == 1)
p = "int";
break;
/* connectat */
case 539:
if (ndx == 0 || ndx == 1)
p = "int";
break;
default:
break;
};

View File

@ -1015,3 +1015,7 @@
uint32_t fcntlrights); }
537 AUE_CAP_FCNTLS_GET NOPROTO { int cap_fcntls_get(int fd, \
uint32_t *fcntlrightsp); }
538 AUE_BINDAT NOPROTO { int bindat(int fd, int s, caddr_t name, \
int namelen); }
539 AUE_CONNECTAT NOPROTO { int connectat(int fd, int s, caddr_t name, \
int namelen); }

View File

@ -234,10 +234,11 @@ static const struct pci_quirk pci_quirks[] = {
{ 0x74501022, PCI_QUIRK_DISABLE_MSI, 0, 0 },
/*
* MSI-X doesn't work with at least LSI SAS1068E passed through by
* VMware.
* MSI-X allocation doesn't work properly for devices passed through
* by VMware up to at least ESXi 5.1.
*/
{ 0x079015ad, PCI_QUIRK_DISABLE_MSI, 0, 0 },
{ 0x079015ad, PCI_QUIRK_DISABLE_MSI, 0, 0 }, /* PCI/PCI-X */
{ 0x07a015ad, PCI_QUIRK_DISABLE_MSI, 0, 0 }, /* PCIe */
/*
* Some virtualization environments emulate an older chipset
@ -3643,11 +3644,11 @@ pci_print_child(device_t dev, device_t child)
return (retval);
}
static struct
static const struct
{
int class;
int subclass;
char *desc;
int class;
int subclass;
const char *desc;
} pci_nomatch_tab[] = {
{PCIC_OLD, -1, "old"},
{PCIC_OLD, PCIS_OLD_NONVGA, "non-VGA display device"},
@ -3739,8 +3740,9 @@ static struct
void
pci_probe_nomatch(device_t dev, device_t child)
{
int i;
char *cp, *scp, *device;
int i;
const char *cp, *scp;
char *device;
/*
* Look for a listing for this device in a loaded device database.
@ -3773,7 +3775,6 @@ pci_probe_nomatch(device_t dev, device_t child)
printf(" at device %d.%d (no driver attached)\n",
pci_get_slot(child), pci_get_function(child));
pci_cfg_save(child, device_get_ivars(child), 1);
return;
}
/*

View File

@ -1,62 +0,0 @@
$FreeBSD$
Announcing the Availability of the
Coda Distributed
Filesystem
for
BSD Unix Systems
Coda is a distributed filesystem like NFS and AFS. It is
freely available, like NFS. But it functions much like AFS in being a
"stateful" filesystem. Coda and AFS cache files on your local
machine to improve performance. But Coda goes a step further than AFS
by letting you access the cached files when there is no available
network, viz. disconnected laptops and network outages. In Coda, both
the client and server are outside the kernel which makes them easier
to experiment with.
To get more information on Coda, I would like to refer people to
http://www.coda.cs.cmu.edu
There is a wealth of documents, papers, and theses there. There is
also a good introduction to the Coda File System in
http://www.coda.cs.cmu.edu/ljpaper/lj.html
Coda was originally developed as an academic prototype/testbed. It is
being polished and rewritten where necessary. Coda is a work in
progress and does have bugs. It is, though, very usable. Our
interest is in making Coda available to as many people as possible and
to have Coda evolve and flourish.
The bulk of the Coda filesystem code supports the Coda client
program, the Coda server program and the utilities needed by both.
All these programs are unix programs and can run equally well on any
Unix platform. Our main development thrust is improving these
programs. There is a small part of Coda that deals with the kernel to
filesystem interface. This code is OS specific (but should not be
platform specific).
Coda is currently available for several OS's and platforms:
Freebsd-2.2.5: i386
Freebsd-2.2.6: i386
Freebsd -current: i386
linux 2.0: i386 & sparc
linux 2.1: i386 & sparc
NetBSD 1.3: i386
NetBSD -current: i386
The relevant sources, binaries, and docs can be found in
ftp://ftp.coda.cs.cmu.edu/pub/coda/
We intend to come out with new Coda releases often, not daily. We
don't want to slight any OS/platform not mentioned above. We are just
limited in our resources as to what we can support internally. We
will be happy to integrate OpenBSD support as well as other OS
support. Also, adding platform support should be relatively easy and
we can discuss this. The only difficulty is that Coda has a light weight
process package. It does some manipulations in assembler which would
have to be redone for a different platform.
There are several mailing lists @coda.cs.cmu.edu that discuss coda:
coda-announce and linux-coda. We are going to revise linux-coda to be
OS neutral, since it is mainly Coda we want to discuss. We appreciate
comments, feedback, bug reports, bug fixes, enhancements, etc.

View File

@ -1,16 +0,0 @@
OOPS:
FreeBSD does not fsync!!!
Near term:
Fix bug in executing/mapping new files.
cfs_mount bug: interaction with cfs_inactive no cfs_unsave.
vref/vn_lock == vget except no VXWANT which may be on.
Review locks: vn_lock/VOP_UNLOCK/lockmgr ...
Medium term:
Add missing VFS methods.
Do performance profile.
Tune hash algorithm used in cfs_subr.
Make MPSAFE
$FreeBSD$

View File

@ -1,206 +0,0 @@
/*-
*
* Coda: an Experimental Distributed File System
* Release 3.1
*
* Copyright (c) 1987-1998 Carnegie Mellon University
* All Rights Reserved
*
* Permission to use, copy, modify and distribute this software and its
* documentation is hereby granted, provided that both the copyright
* notice and this permission notice appear in all copies of the
* software, derivative works or modified versions, and any portions
* thereof, and that both notices appear in supporting documentation, and
* that credit is given to Carnegie Mellon University in all documents
* and publicity pertaining to direct or indirect use of this code or its
* derivatives.
*
* CODA IS AN EXPERIMENTAL SOFTWARE SYSTEM AND IS KNOWN TO HAVE BUGS,
* SOME OF WHICH MAY HAVE SERIOUS CONSEQUENCES. CARNEGIE MELLON ALLOWS
* FREE USE OF THIS SOFTWARE IN ITS "AS IS" CONDITION. CARNEGIE MELLON
* DISCLAIMS ANY LIABILITY OF ANY KIND FOR ANY DAMAGES WHATSOEVER
* RESULTING DIRECTLY OR INDIRECTLY FROM THE USE OF THIS SOFTWARE OR OF
* ANY DERIVATIVE WORK.
*
* Carnegie Mellon encourages users of this software to return any
* improvements or extensions that they make, and to grant Carnegie
* Mellon the rights to redistribute these changes without encumbrance.
*
* @(#) src/sys/coda/cnode.h,v 1.1.1.1 1998/08/29 21:14:52 rvb Exp $
* $FreeBSD$
*
*/
/*-
* Mach Operating System
* Copyright (c) 1990 Carnegie-Mellon University
* Copyright (c) 1989 Carnegie-Mellon University
* All rights reserved. The CMU software License Agreement specifies
* the terms and conditions for use and redistribution.
*/
/*
* This code was written for the Coda filesystem at Carnegie Mellon University.
* Contributers include David Steere, James Kistler, and M. Satyanarayanan.
*/
#ifndef _CNODE_H_
#define _CNODE_H_
#include <sys/vnode.h>
#include <sys/lock.h>
MALLOC_DECLARE(M_CODA);
/*
* Cnode lookup stuff.
*
* NOTE: CODA_CACHESIZE must be a power of 2 for cfshash to work!
*/
#define CODA_CACHESIZE 512
#define CODA_ALLOC(ptr, cast, size) do { \
ptr = (cast)malloc((unsigned long) size, M_CODA, M_WAITOK); \
if (ptr == NULL) \
panic("kernel malloc returns 0 at %s:%d\n", __FILE__, \
__LINE__); \
} while (0)
#define CODA_FREE(ptr, size) free((ptr), M_CODA)
/*
* Used to select debugging statements throughout the cfs code.
*/
extern int codadebug;
extern int coda_printf_delay;
extern int coda_vnop_print_entry;
extern int coda_psdev_print_entry;
extern int coda_vfsop_print_entry;
#define CODADBGMSK(N) (1 << N)
#define CODADEBUG(N, STMT) do { \
if (codadebug & CODADBGMSK(N)) { \
STMT \
} \
} while (0)
#define myprintf(args) do { \
if (coda_printf_delay) \
DELAY(coda_printf_delay); \
printf args ; \
} while (0)
struct cnode {
struct vnode *c_vnode;
u_short c_flags; /* flags (see below) */
struct CodaFid c_fid; /* file handle */
struct vnode *c_ovp; /* open vnode pointer */
u_short c_ocount; /* count of openers */
u_short c_owrite; /* count of open for write */
struct vattr c_vattr; /* attributes */
char *c_symlink; /* pointer to symbolic link */
u_short c_symlen; /* length of symbolic link */
uid_t c_cached_uid; /* cached uid */
accmode_t c_cached_mode; /* cached access mode */
struct cnode *c_next; /* links if on FreeBSD machine */
};
#define VTOC(vp) ((struct cnode *)(vp)->v_data)
#define CTOV(cp) ((struct vnode *)((cp)->c_vnode))
/* flags */
#define C_VATTR 0x01 /* Validity of vattr in the cnode */
#define C_SYMLINK 0x02 /* Validity of symlink pointer in the Code */
#define C_ACCCACHE 0x04 /* Validity of access cache */
#define C_WANTED 0x08 /* Set if lock wanted */
#define C_LOCKED 0x10 /* Set if lock held */
#define C_UNMOUNTING 0X20 /* Set if unmounting */
#define C_PURGING 0x40 /* Set if purging a fid */
#define VALID_VATTR(cp) ((cp->c_flags) & C_VATTR)
#define VALID_SYMLINK(cp) ((cp->c_flags) & C_SYMLINK)
#define VALID_ACCCACHE(cp) ((cp->c_flags) & C_ACCCACHE)
#define IS_UNMOUNTING(cp) ((cp)->c_flags & C_UNMOUNTING)
struct vcomm {
u_long vc_seq;
struct selinfo vc_selproc;
TAILQ_HEAD(, vmsg) vc_requests;
TAILQ_HEAD(, vmsg) vc_replies;
int vc_open;
};
#define VC_OPEN(vcp) ((vcp)->vc_open == 1)
#define MARK_VC_CLOSED(vcp) (vcp)->vc_open = 0
#define MARK_VC_OPEN(vcp) (vcp)->vc_open = 1
struct coda_clstat {
int ncalls; /* client requests */
int nbadcalls; /* upcall failures */
int reqs[CODA_NCALLS]; /* count of each request */
};
extern struct coda_clstat coda_clstat;
/*
* CODA structure to hold mount/filesystem information.
*/
struct coda_mntinfo {
struct vnode *mi_rootvp;
struct mount *mi_vfsp;
struct vcomm mi_vcomm;
struct cdev *dev;
int mi_started;
LIST_ENTRY(coda_mntinfo) mi_list;
};
struct coda_mntinfo *dev2coda_mntinfo(struct cdev *dev);
/*
* vfs pointer to mount info.
*/
#define vftomi(vfsp) ((struct coda_mntinfo *)(vfsp->mnt_data))
#define CODA_MOUNTED(vfsp) (vftomi((vfsp)) != NULL)
/*
* vnode pointer to mount info.
*/
#define vtomi(vp) ((struct coda_mntinfo *)(vp->v_mount->mnt_data))
/*
* Used for identifying usage of "Control" object.
*/
extern struct vnode *coda_ctlvp;
#define IS_CTL_VP(vp) ((vp) == coda_ctlvp)
#define IS_CTL_NAME(vp, name, l) ((l == CODA_CONTROLLEN) \
&& ((vp) == vtomi((vp))->mi_rootvp) && \
strncmp(name, CODA_CONTROL, l) == 0)
/*
* An enum to tell us whether something that will remove a reference to a
* cnode was a downcall or not.
*/
enum dc_status {
IS_DOWNCALL = 6,
NOT_DOWNCALL = 7
};
/* cfs_psdev.h */
int coda_call(struct coda_mntinfo *mntinfo, int inSize, int *outSize,
caddr_t buffer);
extern int coda_kernel_version;
/* cfs_subr.h */
int handleDownCall(struct coda_mntinfo *mnt, int opcode,
union outputArgs *out);
void coda_unmounting(struct mount *whoIam);
int coda_vmflush(struct cnode *cp);
/* cfs_vnodeops.h */
struct cnode *make_coda_node(struct CodaFid *fid, struct mount *vfsp,
short type);
int coda_vnodeopstats_init(void);
/* sigh */
#define CODA_RDWR ((u_long) 31)
#endif /* _CNODE_H_ */

View File

@ -1,838 +0,0 @@
/*-
*
* Coda: an Experimental Distributed File System
* Release 3.1
*
* Copyright (c) 1987-1998 Carnegie Mellon University
* All Rights Reserved
*
* Permission to use, copy, modify and distribute this software and its
* documentation is hereby granted, provided that both the copyright
* notice and this permission notice appear in all copies of the
* software, derivative works or modified versions, and any portions
* thereof, and that both notices appear in supporting documentation, and
* that credit is given to Carnegie Mellon University in all documents
* and publicity pertaining to direct or indirect use of this code or its
* derivatives.
*
* CODA IS AN EXPERIMENTAL SOFTWARE SYSTEM AND IS KNOWN TO HAVE BUGS,
* SOME OF WHICH MAY HAVE SERIOUS CONSEQUENCES. CARNEGIE MELLON ALLOWS
* FREE USE OF THIS SOFTWARE IN ITS "AS IS" CONDITION. CARNEGIE MELLON
* DISCLAIMS ANY LIABILITY OF ANY KIND FOR ANY DAMAGES WHATSOEVER
* RESULTING DIRECTLY OR INDIRECTLY FROM THE USE OF THIS SOFTWARE OR OF
* ANY DERIVATIVE WORK.
*
* Carnegie Mellon encourages users of this software to return any
* improvements or extensions that they make, and to grant Carnegie
* Mellon the rights to redistribute these changes without encumbrance.
*
* @(#) src/sys/coda/coda.h,v 1.1.1.1 1998/08/29 21:14:52 rvb Exp $
* $FreeBSD$
*
*/
/*
*
* Based on cfs.h from Mach, but revamped for increased simplicity.
* Linux modifications by Peter Braam, Aug 1996
*/
#ifndef _CODA_HEADER_
#define _CODA_HEADER_
#ifdef _KERNEL
#include "opt_coda.h" /* for CODA_COMPAT_5 option */
#endif
/* Avoid CODA_COMPAT_5 redefinition in coda5 module */
#if defined (CODA5_MODULE) && !defined(CODA_COMPAT_5)
#define CODA_COMPAT_5
#endif
/* Catch new _KERNEL defn for NetBSD */
#ifdef __NetBSD__
#include <sys/types.h>
#endif
#ifndef CODA_MAXSYMLINKS
#define CODA_MAXSYMLINKS 10
#endif
#if defined(DJGPP) || defined(__CYGWIN32__)
#ifdef _KERNEL
typedef unsigned long u_long;
typedef unsigned int u_int;
typedef unsigned short u_short;
typedef u_long ino_t;
typedef u_long struct cdev *;
typedef void * caddr_t;
#ifdef DOS
typedef unsigned __int64 u_quad_t;
#else
typedef unsigned long long u_quad_t;
#endif
#define inline
struct timespec {
long ts_sec;
long ts_nsec;
};
#else /* DJGPP but not _KERNEL */
#include <sys/types.h>
#include <sys/time.h>
typedef unsigned long long u_quad_t;
#endif /* !_KERNEL */
#endif /* !DJGPP */
#if defined(__linux__)
#define cdev_t u_quad_t
#if !defined(_UQUAD_T_) && (!defined(__GLIBC__) || __GLIBC__ < 2)
#define _UQUAD_T_ 1
typedef unsigned long long u_quad_t;
#endif
#else
#define cdev_t dev_t
#endif
#ifdef __CYGWIN32__
typedef unsigned char u_int8_t;
struct timespec {
time_t tv_sec; /* seconds */
long tv_nsec; /* nanoseconds */
};
#endif
typedef u_int32_t cuid_t;
typedef u_int32_t cgid_t;
/*
* Cfs constants
*/
#define CODA_MAXNAMLEN 255
#define CODA_MAXPATHLEN 1024
#define CODA_MAXSYMLINK 10
/* these are Coda's version of O_RDONLY etc combinations
* to deal with VFS open modes
*/
#define C_O_READ 0x001
#define C_O_WRITE 0x002
#define C_O_TRUNC 0x010
#define C_O_EXCL 0x100
#define C_O_CREAT 0x200
/* these are to find mode bits in Venus */
#define C_M_READ 00400
#define C_M_WRITE 00200
/* for access Venus will use */
#define C_A_C_OK 8 /* Test for writing upon create. */
#define C_A_R_OK 4 /* Test for read permission. */
#define C_A_W_OK 2 /* Test for write permission. */
#define C_A_X_OK 1 /* Test for execute permission. */
#define C_A_F_OK 0 /* Test for existence. */
#ifndef _VENUS_DIRENT_T_
#define _VENUS_DIRENT_T_ 1
struct venus_dirent {
unsigned int d_fileno; /* file number of entry */
unsigned short d_reclen; /* length of this record */
unsigned char d_type; /* file type, see below */
unsigned char d_namlen; /* length of string in d_name */
char d_name[CODA_MAXNAMLEN + 1];/* name must be no longer than this */
};
#undef DIRSIZ
#define DIRSIZ(dp) ((sizeof (struct venus_dirent) - (CODA_MAXNAMLEN+1)) + \
(((dp)->d_namlen+1 + 3) &~ 3))
/*
* File types
*/
#define CDT_UNKNOWN 0
#define CDT_FIFO 1
#define CDT_CHR 2
#define CDT_DIR 4
#define CDT_BLK 6
#define CDT_REG 8
#define CDT_LNK 10
#define CDT_SOCK 12
#define CDT_WHT 14
/*
* Convert between stat structure types and directory types.
*/
#define IFTOCDT(mode) (((mode) & 0170000) >> 12)
#define CDTTOIF(dirtype) ((dirtype) << 12)
#endif
#ifdef CODA_COMPAT_5
struct CodaFid {
u_long Volume;
u_long Vnode;
u_long Unique;
};
static __inline__ ino_t coda_f2i(struct CodaFid *fid)
{
if (!fid) return 0;
return (fid->Unique + (fid->Vnode<<10) + (fid->Volume<<20));
}
static __inline__ char * coda_f2s(struct CodaFid *fid)
{
static char fid_str [35];
snprintf (fid_str, 35, "[%lx.%lx.%lx]", fid->Volume,
fid->Vnode, fid->Unique);
return fid_str;
}
static __inline__ int coda_fid_eq (struct CodaFid *fid1, struct CodaFid *fid2)
{
return (fid1->Volume == fid2->Volume &&
fid1->Vnode == fid2->Vnode &&
fid1->Unique == fid2->Unique);
}
struct coda_cred {
u_int32_t cr_uid, cr_euid, cr_suid, cr_fsuid; /* Real, efftve, set, fs uid*/
u_int32_t cr_groupid, cr_egid, cr_sgid, cr_fsgid; /* same for groups */
};
#else /* CODA_COMPAT_5 */
struct CodaFid {
u_int32_t opaque[4];
};
static __inline__ ino_t coda_f2i(struct CodaFid *fid)
{
if ( ! fid )
return 0;
return (fid->opaque[3] ^ (fid->opaque[2]<<10) ^ (fid->opaque[1]<<20) ^ fid->opaque[0]);
}
static __inline__ char * coda_f2s(struct CodaFid *fid)
{
static char fid_str [35];
snprintf (fid_str, 35, "[%x.%x.%x.%x]", fid->opaque[0],
fid->opaque[1], fid->opaque[2], fid->opaque[3]);
return fid_str;
}
static __inline__ int coda_fid_eq (struct CodaFid *fid1, struct CodaFid *fid2)
{
return (fid1->opaque[0] == fid2->opaque[0] &&
fid1->opaque[1] == fid2->opaque[1] &&
fid1->opaque[2] == fid2->opaque[2] &&
fid1->opaque[3] == fid2->opaque[3]);
}
#endif /* CODA_COMPAT_5 */
#ifndef _VENUS_VATTR_T_
#define _VENUS_VATTR_T_
/*
* Vnode types. VNON means no type.
*/
enum coda_vtype { C_VNON, C_VREG, C_VDIR, C_VBLK, C_VCHR, C_VLNK, C_VSOCK, C_VFIFO, C_VBAD };
struct coda_vattr {
long va_type; /* vnode type (for create) */
u_short va_mode; /* files access mode and type */
short va_nlink; /* number of references to file */
cuid_t va_uid; /* owner user id */
cgid_t va_gid; /* owner group id */
long va_fileid; /* file id */
u_quad_t va_size; /* file size in bytes */
long va_blocksize; /* blocksize preferred for i/o */
struct timespec va_atime; /* time of last access */
struct timespec va_mtime; /* time of last modification */
struct timespec va_ctime; /* time file changed */
u_long va_gen; /* generation number of file */
u_long va_flags; /* flags defined for file */
cdev_t va_rdev; /* device special file represents */
u_quad_t va_bytes; /* bytes of disk space held by file */
u_quad_t va_filerev; /* file modification number */
};
#endif
/* structure used by CODA_STATFS for getting cache information from venus */
struct coda_statfs {
int32_t f_blocks;
int32_t f_bfree;
int32_t f_bavail;
int32_t f_files;
int32_t f_ffree;
};
/*
* Kernel <--> Venus communications.
*/
#define CODA_ROOT 2
#define CODA_OPEN_BY_FD 3
#define CODA_OPEN 4
#define CODA_CLOSE 5
#define CODA_IOCTL 6
#define CODA_GETATTR 7
#define CODA_SETATTR 8
#define CODA_ACCESS 9
#define CODA_LOOKUP 10
#define CODA_CREATE 11
#define CODA_REMOVE 12
#define CODA_LINK 13
#define CODA_RENAME 14
#define CODA_MKDIR 15
#define CODA_RMDIR 16
#define CODA_READDIR 17
#define CODA_SYMLINK 18
#define CODA_READLINK 19
#define CODA_FSYNC 20
#define CODA_INACTIVE 21
#define CODA_VGET 22
#define CODA_SIGNAL 23
#define CODA_REPLACE 24
#define CODA_FLUSH 25
#define CODA_PURGEUSER 26
#define CODA_ZAPFILE 27
#define CODA_ZAPDIR 28
#define CODA_PURGEFID 30
#define CODA_OPEN_BY_PATH 31
#define CODA_RESOLVE 32
#define CODA_REINTEGRATE 33
#define CODA_STATFS 34
#define CODA_NCALLS 35
#define DOWNCALL(opcode) (opcode >= CODA_REPLACE && opcode <= CODA_PURGEFID)
#define VC_MAXDATASIZE 8192
#define VC_MAXMSGSIZE sizeof(union inputArgs)+sizeof(union outputArgs) +\
VC_MAXDATASIZE
#define CIOC_KERNEL_VERSION _IOWR('c', 10, int)
#if 0
/* don't care about kernel version number */
#define CODA_KERNEL_VERSION 0
/* The old venus 4.6 compatible interface */
#define CODA_KERNEL_VERSION 1
#endif /* realms/cells */
#ifdef CODA_COMPAT_5
/* venus_lookup gets an extra parameter to aid windows.*/
#define CODA_KERNEL_VERSION 2
#else
/* 128-bit fids for realms */
#define CODA_KERNEL_VERSION 3
#endif
/*
* Venus <-> Coda RPC arguments
*/
#ifdef CODA_COMPAT_5
struct coda_in_hdr {
unsigned long opcode;
unsigned long unique; /* Keep multiple outstanding msgs distinct */
u_short pid; /* Common to all */
u_short pgid; /* Common to all */
u_short sid; /* Common to all */
struct coda_cred cred; /* Common to all */
};
#else
struct coda_in_hdr {
u_int32_t opcode;
u_int32_t unique; /* Keep multiple outstanding msgs distinct */
pid_t pid;
pid_t pgid;
cuid_t uid;
};
#endif
/* Really important that opcode and unique are 1st two fields! */
struct coda_out_hdr {
u_int32_t opcode;
u_int32_t unique;
u_int32_t result;
};
/* coda_root: NO_IN */
struct coda_root_out {
struct coda_out_hdr oh;
struct CodaFid Fid;
};
struct coda_root_in {
struct coda_in_hdr in;
};
/* coda_sync: */
/* Nothing needed for coda_sync */
/* coda_open: */
struct coda_open_in {
struct coda_in_hdr ih;
struct CodaFid Fid;
int flags;
};
struct coda_open_out {
struct coda_out_hdr oh;
cdev_t dev;
ino_t inode;
};
/* coda_close: */
struct coda_close_in {
struct coda_in_hdr ih;
struct CodaFid Fid;
int flags;
};
struct coda_close_out {
struct coda_out_hdr out;
};
/* coda_ioctl: */
struct coda_ioctl_in {
struct coda_in_hdr ih;
struct CodaFid Fid;
int cmd;
int len;
int rwflag;
char *data; /* Place holder for data. */
};
struct coda_ioctl_out {
struct coda_out_hdr oh;
int len;
caddr_t data; /* Place holder for data. */
};
/* coda_getattr: */
struct coda_getattr_in {
struct coda_in_hdr ih;
struct CodaFid Fid;
};
struct coda_getattr_out {
struct coda_out_hdr oh;
struct coda_vattr attr;
};
/* coda_setattr: NO_OUT */
struct coda_setattr_in {
struct coda_in_hdr ih;
struct CodaFid Fid;
struct coda_vattr attr;
};
struct coda_setattr_out {
struct coda_out_hdr out;
};
/* coda_access: NO_OUT */
struct coda_access_in {
struct coda_in_hdr ih;
struct CodaFid Fid;
int flags;
};
struct coda_access_out {
struct coda_out_hdr out;
};
/* lookup flags */
#define CLU_CASE_SENSITIVE 0x01
#define CLU_CASE_INSENSITIVE 0x02
/* coda_lookup: */
struct coda_lookup_in {
struct coda_in_hdr ih;
struct CodaFid Fid;
int name; /* Place holder for data. */
int flags;
};
struct coda_lookup_out {
struct coda_out_hdr oh;
struct CodaFid Fid;
int vtype;
};
/* coda_create: */
struct coda_create_in {
struct coda_in_hdr ih;
struct CodaFid Fid;
struct coda_vattr attr;
int excl;
int mode;
int name; /* Place holder for data. */
};
struct coda_create_out {
struct coda_out_hdr oh;
struct CodaFid Fid;
struct coda_vattr attr;
};
/* coda_remove: NO_OUT */
struct coda_remove_in {
struct coda_in_hdr ih;
struct CodaFid Fid;
int name; /* Place holder for data. */
};
struct coda_remove_out {
struct coda_out_hdr out;
};
/* coda_link: NO_OUT */
struct coda_link_in {
struct coda_in_hdr ih;
struct CodaFid sourceFid; /* cnode to link *to* */
struct CodaFid destFid; /* Directory in which to place link */
int tname; /* Place holder for data. */
};
struct coda_link_out {
struct coda_out_hdr out;
};
/* coda_rename: NO_OUT */
struct coda_rename_in {
struct coda_in_hdr ih;
struct CodaFid sourceFid;
int srcname;
struct CodaFid destFid;
int destname;
};
struct coda_rename_out {
struct coda_out_hdr out;
};
/* coda_mkdir: */
struct coda_mkdir_in {
struct coda_in_hdr ih;
struct CodaFid Fid;
struct coda_vattr attr;
int name; /* Place holder for data. */
};
struct coda_mkdir_out {
struct coda_out_hdr oh;
struct CodaFid Fid;
struct coda_vattr attr;
};
/* coda_rmdir: NO_OUT */
struct coda_rmdir_in {
struct coda_in_hdr ih;
struct CodaFid Fid;
int name; /* Place holder for data. */
};
struct coda_rmdir_out {
struct coda_out_hdr out;
};
/* coda_readdir: */
struct coda_readdir_in {
struct coda_in_hdr ih;
struct CodaFid Fid;
int count;
int offset;
};
struct coda_readdir_out {
struct coda_out_hdr oh;
int size;
caddr_t data; /* Place holder for data. */
};
/* coda_symlink: NO_OUT */
struct coda_symlink_in {
struct coda_in_hdr ih;
struct CodaFid Fid; /* Directory to put symlink in */
int srcname;
struct coda_vattr attr;
int tname;
};
struct coda_symlink_out {
struct coda_out_hdr out;
};
/* coda_readlink: */
struct coda_readlink_in {
struct coda_in_hdr ih;
struct CodaFid Fid;
};
struct coda_readlink_out {
struct coda_out_hdr oh;
int count;
caddr_t data; /* Place holder for data. */
};
/* coda_fsync: NO_OUT */
struct coda_fsync_in {
struct coda_in_hdr ih;
struct CodaFid Fid;
};
struct coda_fsync_out {
struct coda_out_hdr out;
};
/* coda_inactive: NO_OUT */
struct coda_inactive_in {
struct coda_in_hdr ih;
struct CodaFid Fid;
};
/* coda_vget: */
struct coda_vget_in {
struct coda_in_hdr ih;
struct CodaFid Fid;
};
struct coda_vget_out {
struct coda_out_hdr oh;
struct CodaFid Fid;
int vtype;
};
/* CODA_SIGNAL is out-of-band, doesn't need data. */
/* CODA_INVALIDATE is a venus->kernel call */
/* CODA_FLUSH is a venus->kernel call */
/* coda_purgeuser: */
/* CODA_PURGEUSER is a venus->kernel call */
struct coda_purgeuser_out {
struct coda_out_hdr oh;
#ifdef CODA_COMPAT_5
struct coda_cred cred;
#else
cuid_t uid;
#endif
};
/* coda_zapfile: */
/* CODA_ZAPFILE is a venus->kernel call */
struct coda_zapfile_out {
struct coda_out_hdr oh;
struct CodaFid Fid;
};
/* coda_zapdir: */
/* CODA_ZAPDIR is a venus->kernel call */
struct coda_zapdir_out {
struct coda_out_hdr oh;
struct CodaFid Fid;
};
/* coda_zapnode: */
/* CODA_ZAPVNODE is a venus->kernel call */
struct coda_zapvnode_out {
struct coda_out_hdr oh;
#ifdef CODA_COMPAT_5
struct coda_cred cred;
#endif
struct CodaFid Fid;
};
/* coda_purgefid: */
/* CODA_PURGEFID is a venus->kernel call */
struct coda_purgefid_out {
struct coda_out_hdr oh;
struct CodaFid Fid;
};
/* coda_replace: */
/* CODA_REPLACE is a venus->kernel call */
struct coda_replace_out { /* coda_replace is a venus->kernel call */
struct coda_out_hdr oh;
struct CodaFid NewFid;
struct CodaFid OldFid;
};
/* coda_open_by_fd: */
struct coda_open_by_fd_in {
struct coda_in_hdr ih;
struct CodaFid Fid;
int flags;
};
struct coda_open_by_fd_out {
struct coda_out_hdr oh;
int fd;
#ifdef _KERNEL
/* not passed from userspace but used in-kernel only */
struct vnode *vp;
#endif
};
/* coda_open_by_path: */
struct coda_open_by_path_in {
struct coda_in_hdr ih;
struct CodaFid Fid;
int flags;
};
struct coda_open_by_path_out {
struct coda_out_hdr oh;
int path;
};
/* coda_statfs: NO_IN */
struct coda_statfs_in {
struct coda_in_hdr ih;
};
struct coda_statfs_out {
struct coda_out_hdr oh;
struct coda_statfs stat;
};
/*
* Occasionally, we don't cache the fid returned by CODA_LOOKUP.
* For instance, if the fid is inconsistent.
* This case is handled by setting the top bit of the type result parameter.
*/
#define CODA_NOCACHE 0x80000000
union inputArgs {
struct coda_in_hdr ih; /* NB: every struct below begins with an ih */
struct coda_open_in coda_open;
struct coda_close_in coda_close;
struct coda_ioctl_in coda_ioctl;
struct coda_getattr_in coda_getattr;
struct coda_setattr_in coda_setattr;
struct coda_access_in coda_access;
struct coda_lookup_in coda_lookup;
struct coda_create_in coda_create;
struct coda_remove_in coda_remove;
struct coda_link_in coda_link;
struct coda_rename_in coda_rename;
struct coda_mkdir_in coda_mkdir;
struct coda_rmdir_in coda_rmdir;
struct coda_readdir_in coda_readdir;
struct coda_symlink_in coda_symlink;
struct coda_readlink_in coda_readlink;
struct coda_fsync_in coda_fsync;
struct coda_vget_in coda_vget;
struct coda_open_by_fd_in coda_open_by_fd;
struct coda_open_by_path_in coda_open_by_path;
struct coda_statfs_in coda_statfs;
};
union outputArgs {
struct coda_out_hdr oh; /* NB: every struct below begins with an oh */
struct coda_root_out coda_root;
struct coda_open_out coda_open;
struct coda_ioctl_out coda_ioctl;
struct coda_getattr_out coda_getattr;
struct coda_lookup_out coda_lookup;
struct coda_create_out coda_create;
struct coda_mkdir_out coda_mkdir;
struct coda_readdir_out coda_readdir;
struct coda_readlink_out coda_readlink;
struct coda_vget_out coda_vget;
struct coda_purgeuser_out coda_purgeuser;
struct coda_zapfile_out coda_zapfile;
struct coda_zapdir_out coda_zapdir;
struct coda_zapvnode_out coda_zapvnode;
struct coda_purgefid_out coda_purgefid;
struct coda_replace_out coda_replace;
struct coda_open_by_fd_out coda_open_by_fd;
struct coda_open_by_path_out coda_open_by_path;
struct coda_statfs_out coda_statfs;
};
union coda_downcalls {
/* CODA_INVALIDATE is a venus->kernel call */
/* CODA_FLUSH is a venus->kernel call */
struct coda_purgeuser_out purgeuser;
struct coda_zapfile_out zapfile;
struct coda_zapdir_out zapdir;
struct coda_zapvnode_out zapvnode;
struct coda_purgefid_out purgefid;
struct coda_replace_out replace;
};
/*
* Used for identifying usage of "Control" and pioctls
*/
#define PIOCPARM_MASK 0x0000ffff
struct ViceIoctl {
caddr_t in, out; /* Data to be transferred in, or out */
unsigned short in_size; /* Size of input buffer <= 8K */
unsigned short out_size; /* Maximum size of output buffer, <= 8K */
};
#if defined(__CYGWIN32__) || defined(DJGPP)
struct PioctlData {
unsigned long cmd;
const char *path;
int follow;
struct ViceIoctl vi;
};
#else
struct PioctlData {
const char *path;
int follow;
struct ViceIoctl vi;
};
#endif
#define CODA_CONTROL ".CONTROL"
#define CODA_CONTROLLEN 8
#define CTL_VOL -1
#define CTL_VNO -1
#define CTL_UNI -1
#define CTL_INO -1
#define CTL_FILE "/coda/.CONTROL"
#ifdef CODA_COMPAT_5
#define CTL_FID { -1, -1, -1 }
#define IS_CTL_FID(fidp) ((fidp)->Volume == -1 &&\
(fidp)->Vnode == -1 &&\
(fidp)->Unique == -1)
#define INVAL_FID { 0, 0, 0 }
#else
#define CTL_FID { { -1, -1, -1, -1 } }
#define IS_CTL_FID(fidp) ((fidp)->opaque[1] == CTL_VOL && \
(fidp)->opaque[2] == CTL_VNO && \
(fidp)->opaque[3] == CTL_UNI)
#define INVAL_FID { { 0, 0, 0, 0 } }
#endif
/* Data passed to mount */
#define CODA_MOUNT_VERSION 1
struct coda_mount_data {
int version;
int fd; /* Opened device */
};
#endif

View File

@ -1,148 +0,0 @@
/*-
* Coda: an Experimental Distributed File System
* Release 3.1
*
* Copyright (c) 1987-1998 Carnegie Mellon University
* All Rights Reserved
*
* Permission to use, copy, modify and distribute this software and its
* documentation is hereby granted, provided that both the copyright
* notice and this permission notice appear in all copies of the
* software, derivative works or modified versions, and any portions
* thereof, and that both notices appear in supporting documentation, and
* that credit is given to Carnegie Mellon University in all documents
* and publicity pertaining to direct or indirect use of this code or its
* derivatives.
*
* CODA IS AN EXPERIMENTAL SOFTWARE SYSTEM AND IS KNOWN TO HAVE BUGS,
* SOME OF WHICH MAY HAVE SERIOUS CONSEQUENCES. CARNEGIE MELLON ALLOWS
* FREE USE OF THIS SOFTWARE IN ITS "AS IS" CONDITION. CARNEGIE MELLON
* DISCLAIMS ANY LIABILITY OF ANY KIND FOR ANY DAMAGES WHATSOEVER
* RESULTING DIRECTLY OR INDIRECTLY FROM THE USE OF THIS SOFTWARE OR OF
* ANY DERIVATIVE WORK.
*
* Carnegie Mellon encourages users of this software to return any
* improvements or extensions that they make, and to grant Carnegie
* Mellon the rights to redistribute these changes without encumbrance.
*
* @(#) src/sys/coda/coda_fbsd.cr,v 1.1.1.1 1998/08/29 21:14:52 rvb Exp $
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/conf.h>
#include <sys/fcntl.h>
#include <sys/kernel.h>
#include <sys/lock.h>
#include <sys/malloc.h>
#include <sys/module.h>
#include <sys/ucred.h>
#include <sys/vnode.h>
#include <vm/vm.h>
#include <vm/vnode_pager.h>
#include <fs/coda/coda.h>
#include <fs/coda/cnode.h>
#include <fs/coda/coda_vnops.h>
#include <fs/coda/coda_psdev.h>
static struct cdevsw codadevsw = {
.d_version = D_VERSION,
.d_flags = D_NEEDGIANT,
.d_open = vc_open,
.d_close = vc_close,
.d_read = vc_read,
.d_write = vc_write,
.d_ioctl = vc_ioctl,
.d_poll = vc_poll,
.d_name = "coda",
};
static eventhandler_tag clonetag;
static LIST_HEAD(, coda_mntinfo) coda_mnttbl;
/*
* For DEVFS, using bpf & tun drivers as examples.
*
* XXX: Why use a cloned interface, aren't we really just interested in
* having a single /dev/cfs0? It's not clear the coda module knows what to
* do with more than one.
*/
static void coda_fbsd_clone(void *arg, struct ucred *cred, char *name,
int namelen, struct cdev **dev);
static int
codadev_modevent(module_t mod, int type, void *data)
{
struct coda_mntinfo *mnt;
switch (type) {
case MOD_LOAD:
LIST_INIT(&coda_mnttbl);
clonetag = EVENTHANDLER_REGISTER(dev_clone, coda_fbsd_clone,
0, 1000);
break;
case MOD_UNLOAD:
/*
* XXXRW: At the very least, a busy check should occur here
* to prevent untimely unload. Much more serious collection
* of allocated memory needs to take place; right now we leak
* like a sieve.
*/
EVENTHANDLER_DEREGISTER(dev_clone, clonetag);
while ((mnt = LIST_FIRST(&coda_mnttbl)) != NULL) {
LIST_REMOVE(mnt, mi_list);
destroy_dev(mnt->dev);
free(mnt, M_CODA);
}
break;
default:
return (EOPNOTSUPP);
}
return (0);
}
static moduledata_t codadev_mod = {
"codadev",
codadev_modevent,
NULL
};
DECLARE_MODULE(codadev, codadev_mod, SI_SUB_DRIVERS, SI_ORDER_MIDDLE);
static void
coda_fbsd_clone(void *arg, struct ucred *cred, char *name, int namelen,
struct cdev **dev)
{
struct coda_mntinfo *mnt;
int u;
if (*dev != NULL)
return;
if (dev_stdclone(name, NULL, "cfs", &u) != 1)
return;
*dev = make_dev(&codadevsw, u, UID_ROOT, GID_WHEEL, 0600,
"cfs%d", u);
dev_ref(*dev);
mnt = malloc(sizeof(struct coda_mntinfo), M_CODA, M_WAITOK|M_ZERO);
LIST_INSERT_HEAD(&coda_mnttbl, mnt, mi_list);
mnt->dev = *dev;
}
struct coda_mntinfo *
dev2coda_mntinfo(struct cdev *dev)
{
struct coda_mntinfo *mnt;
LIST_FOREACH(mnt, &coda_mnttbl, mi_list) {
if (mnt->dev == dev)
return (mnt);
}
return (NULL);
}

View File

@ -1,73 +0,0 @@
/*-
*
* Coda: an Experimental Distributed File System
* Release 3.1
*
* Copyright (c) 1987-1998 Carnegie Mellon University
* All Rights Reserved
*
* Permission to use, copy, modify and distribute this software and its
* documentation is hereby granted, provided that both the copyright
* notice and this permission notice appear in all copies of the
* software, derivative works or modified versions, and any portions
* thereof, and that both notices appear in supporting documentation, and
* that credit is given to Carnegie Mellon University in all documents
* and publicity pertaining to direct or indirect use of this code or its
* derivatives.
*
* CODA IS AN EXPERIMENTAL SOFTWARE SYSTEM AND IS KNOWN TO HAVE BUGS,
* SOME OF WHICH MAY HAVE SERIOUS CONSEQUENCES. CARNEGIE MELLON ALLOWS
* FREE USE OF THIS SOFTWARE IN ITS "AS IS" CONDITION. CARNEGIE MELLON
* DISCLAIMS ANY LIABILITY OF ANY KIND FOR ANY DAMAGES WHATSOEVER
* RESULTING DIRECTLY OR INDIRECTLY FROM THE USE OF THIS SOFTWARE OR OF
* ANY DERIVATIVE WORK.
*
* Carnegie Mellon encourages users of this software to return any
* improvements or extensions that they make, and to grant Carnegie
* Mellon the rights to redistribute these changes without encumbrance.
*
* @(#) src/sys/coda/coda_io.h,v 1.1.1.1 1998/08/29 21:14:52 rvb Exp $
* $FreeBSD$
*
*/
/*-
* Mach Operating System
* Copyright (c) 1990 Carnegie-Mellon University
* Copyright (c) 1989 Carnegie-Mellon University
* All rights reserved. The CMU software License Agreement specifies
* the terms and conditions for use and redistribution.
*/
/*
* This code was written for the Coda filesystem at Carnegie Mellon University.
* Contributers include David Steere, James Kistler, and M. Satyanarayanan.
*/
#ifndef _CODAIO_H_
#define _CODAIO_H_
/*
* Define ioctl commands for vcioctl, /dev/cfs.
*
* Resize Coda namecache.
*/
#define CODARESIZE _IOW('c', 1, struct coda_resize)
/*
* Collect statistics.
*/
#define CODASTATS _IO('c', 2)
/*
* Print cache.
*/
#define CODAPRINT _IO('c', 3)
#define CODATEST _IO('c', 4)
struct coda_resize {
int hashsize;
int heapsize;
};
#endif /* !_CODAIO_H_ */

View File

@ -1,130 +0,0 @@
/*-
*
* Coda: an Experimental Distributed File System
* Release 3.1
*
* Copyright (c) 1987-1998 Carnegie Mellon University
* All Rights Reserved
*
* Permission to use, copy, modify and distribute this software and its
* documentation is hereby granted, provided that both the copyright
* notice and this permission notice appear in all copies of the
* software, derivative works or modified versions, and any portions
* thereof, and that both notices appear in supporting documentation, and
* that credit is given to Carnegie Mellon University in all documents
* and publicity pertaining to direct or indirect use of this code or its
* derivatives.
*
* CODA IS AN EXPERIMENTAL SOFTWARE SYSTEM AND IS KNOWN TO HAVE BUGS,
* SOME OF WHICH MAY HAVE SERIOUS CONSEQUENCES. CARNEGIE MELLON ALLOWS
* FREE USE OF THIS SOFTWARE IN ITS "AS IS" CONDITION. CARNEGIE MELLON
* DISCLAIMS ANY LIABILITY OF ANY KIND FOR ANY DAMAGES WHATSOEVER
* RESULTING DIRECTLY OR INDIRECTLY FROM THE USE OF THIS SOFTWARE OR OF
* ANY DERIVATIVE WORK.
*
* Carnegie Mellon encourages users of this software to return any
* improvements or extensions that they make, and to grant Carnegie
* Mellon the rights to redistribute these changes without encumbrance.
*
* @(#) src/sys/coda/coda_opstats.h,v 1.1.1.1 1998/08/29 21:14:52 rvb Exp $
* $FreeBSD$
*
*/
#ifndef _CODA_OPSTATS_H_
#define _CODA_OPSTATS_H_
/*
* Operation stats: what the minicache can intercept that *isn't* seen by
* venus. These stats are kept to augment the stats maintained by the
* Volume-Session mechanism.
*/
/*-
* vfsops:
* mount: not currently bounced to Venus
* umount: nope
* root: only first call, rest is cached.
* statfs: none (bogus)
* sync: none (bogus)
* vget: all
*/
#define CODA_MOUNT_STATS 0
#define CODA_UMOUNT_STATS 1
#define CODA_ROOT_STATS 2
#define CODA_STATFS_STATS 3
#define CODA_SYNC_STATS 4
#define CODA_VGET_STATS 5
#define CODA_VFSOPS_SIZE 6
/*-
* vnodeops:
* open: all to venus
* close: all to venus
* rdrw: bogus. Maybe redirected to UFS.
* May call open/close for internal opens/closes
* (Does exec not call open?)
* ioctl: causes a lookupname
* passes through
* select: can't get there from here.
* getattr: can be satsified by cache
* setattr: all go through
* access: can be satisfied by cache
* readlink: can be satisfied by cache
* fsync: passes through
* inactive: passes through
* lookup: can be satisfied by cache
* create: passes through
* remove: passes through
* link: passes through
* rename: passes through
* mkdir: passes through
* rmdir: passes through
* symlink: passes through
* readdir: may be redirected to UFS
* may cause an "internal" open/close
*/
#define CODA_OPEN_STATS 0
#define CODA_CLOSE_STATS 1
#define CODA_RDWR_STATS 2
#define CODA_IOCTL_STATS 3
#define CODA_SELECT_STATS 4
#define CODA_GETATTR_STATS 5
#define CODA_SETATTR_STATS 6
#define CODA_ACCESS_STATS 7
#define CODA_READLINK_STATS 8
#define CODA_FSYNC_STATS 9
#define CODA_INACTIVE_STATS 10
#define CODA_LOOKUP_STATS 11
#define CODA_CREATE_STATS 12
#define CODA_REMOVE_STATS 13
#define CODA_LINK_STATS 14
#define CODA_RENAME_STATS 15
#define CODA_MKDIR_STATS 16
#define CODA_RMDIR_STATS 17
#define CODA_SYMLINK_STATS 18
#define CODA_READDIR_STATS 19
#define CODA_VNODEOPS_SIZE 20
/*
* I propose the following structres:
*/
struct coda_op_stats {
int opcode; /* vfs opcode */
long entries; /* number of times call attempted */
long sat_intrn; /* number of times call satisfied by cache */
long unsat_intrn; /* number of times call failed in cache, but */
/* was not bounced to venus proper. */
long gen_intrn; /* number of times call generated internally */
/* (do we need that?) */
};
/*
* With each call to the minicache, we'll bump the counters whenver a call is
* satisfied internally (through the cache or through a redirect), and
* whenever an operation is caused internally. Then, we can add the total
* operations caught by the minicache to the world-wide totals, and leave a
* caveat for the specific graphs later.
*/
#endif /* !_CODA_OPSTATS_H_ */

View File

@ -1,69 +0,0 @@
/*-
*
* Coda: an Experimental Distributed File System
* Release 3.1
*
* Copyright (c) 1987-1998 Carnegie Mellon University
* All Rights Reserved
*
* Permission to use, copy, modify and distribute this software and its
* documentation is hereby granted, provided that both the copyright
* notice and this permission notice appear in all copies of the
* software, derivative works or modified versions, and any portions
* thereof, and that both notices appear in supporting documentation, and
* that credit is given to Carnegie Mellon University in all documents
* and publicity pertaining to direct or indirect use of this code or its
* derivatives.
*
* CODA IS AN EXPERIMENTAL SOFTWARE SYSTEM AND IS KNOWN TO HAVE BUGS,
* SOME OF WHICH MAY HAVE SERIOUS CONSEQUENCES. CARNEGIE MELLON ALLOWS
* FREE USE OF THIS SOFTWARE IN ITS "AS IS" CONDITION. CARNEGIE MELLON
* DISCLAIMS ANY LIABILITY OF ANY KIND FOR ANY DAMAGES WHATSOEVER
* RESULTING DIRECTLY OR INDIRECTLY FROM THE USE OF THIS SOFTWARE OR OF
* ANY DERIVATIVE WORK.
*
* Carnegie Mellon encourages users of this software to return any
* improvements or extensions that they make, and to grant Carnegie
* Mellon the rights to redistribute these changes without encumbrance.
*
* @(#) src/sys/coda/coda_pioctl.h,v 1.1.1.1 1998/08/29 21:14:52 rvb Exp $
* $FreeBSD$
*
*/
/*-
* Mach Operating System
* Copyright (c) 1989 Carnegie-Mellon University
* Copyright (c) 1988 Carnegie-Mellon University
* Copyright (c) 1987 Carnegie-Mellon University
* All rights reserved. The CMU software License Agreement specifies
* the terms and conditions for use and redistribution.
*/
/*
* ITC Remote filesystem - vice ioctl interface module
*
* TODO: Find /usr/local/include/viceioctl.h.
*/
#ifndef _SYS_PIOCTL_H_
#define _SYS_PIOCTL_H_
/*
* The 2K limits above are a consequence of the size of the kernel buffer
* used to buffer requests from the user to venus--2*MAXPATHLEN. The buffer
* pointers may be null, or the counts may be 0 if there are no input or
* output parameters.
*/
#define _VICEIOCTL(id) ((unsigned int )_IOW('V', id, struct ViceIoctl))
/*
* Use this macro to define up to 256 vice ioctl's. These ioctl's all
* potentially have in/out parameters--this depends upon the values in the
* ViceIoctl structure. This structure is itself passed into the kernel by
* the normal ioctl parameter passing mechanism.
*/
#define _VALIDVICEIOCTL(com) (com >= _VICEIOCTL(0) && \
com <= _VICEIOCTL(255))
#endif /* !_SYS_PIOCTL_H_ */

View File

@ -1,675 +0,0 @@
/*-
* Coda: an Experimental Distributed File System
* Release 3.1
*
* Copyright (c) 1987-1998 Carnegie Mellon University
* All Rights Reserved
*
* Permission to use, copy, modify and distribute this software and its
* documentation is hereby granted, provided that both the copyright
* notice and this permission notice appear in all copies of the
* software, derivative works or modified versions, and any portions
* thereof, and that both notices appear in supporting documentation, and
* that credit is given to Carnegie Mellon University in all documents
* and publicity pertaining to direct or indirect use of this code or its
* derivatives.
*
* CODA IS AN EXPERIMENTAL SOFTWARE SYSTEM AND IS KNOWN TO HAVE BUGS,
* SOME OF WHICH MAY HAVE SERIOUS CONSEQUENCES. CARNEGIE MELLON ALLOWS
* FREE USE OF THIS SOFTWARE IN ITS "AS IS" CONDITION. CARNEGIE MELLON
* DISCLAIMS ANY LIABILITY OF ANY KIND FOR ANY DAMAGES WHATSOEVER
* RESULTING DIRECTLY OR INDIRECTLY FROM THE USE OF THIS SOFTWARE OR OF
* ANY DERIVATIVE WORK.
*
* Carnegie Mellon encourages users of this software to return any
* improvements or extensions that they make, and to grant Carnegie
* Mellon the rights to redistribute these changes without encumbrance.
*
* @(#) src/sys/coda/coda_psdev.c,v 1.1.1.1 1998/08/29 21:14:52 rvb Exp $
*/
/*-
* Mach Operating System
* Copyright (c) 1989 Carnegie-Mellon University
* All rights reserved. The CMU software License Agreement specifies
* the terms and conditions for use and redistribution.
*/
/*
* This code was written for the Coda filesystem at Carnegie Mellon
* University. Contributers include David Steere, James Kistler, and
* M. Satyanarayanan. */
/*
* These routines define the psuedo device for communication between Coda's
* Venus and Minicache in Mach 2.6. They used to be in cfs_subr.c, but I
* moved them to make it easier to port the Minicache without porting coda.
* -- DCS 10/12/94
*/
/*
* These routines are the device entry points for Venus.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/capability.h>
#include <sys/conf.h>
#include <sys/ioccom.h>
#include <sys/kernel.h>
#include <sys/lock.h>
#include <sys/malloc.h>
#include <sys/file.h> /* must come after sys/malloc.h */
#include <sys/mount.h>
#include <sys/mutex.h>
#include <sys/poll.h>
#include <sys/proc.h>
#include <sys/filedesc.h>
#include <fs/coda/coda.h>
#include <fs/coda/cnode.h>
#include <fs/coda/coda_io.h>
#include <fs/coda/coda_psdev.h>
/*
* Variables to determine how Coda sleeps and whether or not it is
* interruptible when it does sleep waiting for Venus.
*/
/* #define CTL_C */
#ifdef CTL_C
#include <sys/signalvar.h>
#endif
int coda_psdev_print_entry = 0;
static int outstanding_upcalls = 0;
int coda_call_sleep = PZERO - 1;
#ifdef CTL_C
int coda_pcatch = PCATCH;
#else
#endif
#define ENTRY do { \
if (coda_psdev_print_entry) \
myprintf(("Entered %s\n", __func__)); \
} while (0)
struct vmsg {
TAILQ_ENTRY(vmsg) vm_chain;
caddr_t vm_data;
u_short vm_flags;
u_short vm_inSize; /* Size is at most 5000 bytes */
u_short vm_outSize;
u_short vm_opcode; /* Copied from data to save ptr deref */
int vm_unique;
caddr_t vm_sleep; /* Not used by Mach. */
};
#define VM_READ 1
#define VM_WRITE 2
#define VM_INTR 4 /* Unused. */
int
vc_open(struct cdev *dev, int flag, int mode, struct thread *td)
{
struct vcomm *vcp;
struct coda_mntinfo *mnt;
ENTRY;
mnt = dev2coda_mntinfo(dev);
KASSERT(mnt, ("Coda: tried to open uninitialized cfs device"));
vcp = &mnt->mi_vcomm;
if (VC_OPEN(vcp))
return (EBUSY);
bzero(&(vcp->vc_selproc), sizeof (struct selinfo));
TAILQ_INIT(&vcp->vc_requests);
TAILQ_INIT(&vcp->vc_replies);
MARK_VC_OPEN(vcp);
mnt->mi_vfsp = NULL;
mnt->mi_rootvp = NULL;
return (0);
}
int
vc_close(struct cdev *dev, int flag, int mode, struct thread *td)
{
struct vcomm *vcp;
struct vmsg *vmp, *nvmp = NULL;
struct coda_mntinfo *mi;
int err;
ENTRY;
mi = dev2coda_mntinfo(dev);
KASSERT(mi, ("Coda: closing unknown cfs device"));
vcp = &mi->mi_vcomm;
KASSERT(VC_OPEN(vcp), ("Coda: closing unopened cfs device"));
/*
* Prevent future operations on this vfs from succeeding by
* auto-unmounting any vfs mounted via this device. This frees user
* or sysadm from having to remember where all mount points are
* located. Put this before WAKEUPs to avoid queuing new messages
* between the WAKEUP and the unmount (which can happen if we're
* unlucky).
*/
if (mi->mi_rootvp == NULL) {
/*
* Just a simple open/close with no mount.
*/
MARK_VC_CLOSED(vcp);
return (0);
}
/*
* Let unmount know this is for real.
*/
VTOC(mi->mi_rootvp)->c_flags |= C_UNMOUNTING;
coda_unmounting(mi->mi_vfsp);
/*
* Wakeup clients so they can return.
*/
outstanding_upcalls = 0;
TAILQ_FOREACH_SAFE(vmp, &vcp->vc_requests, vm_chain, nvmp) {
/*
* Free signal request messages and don't wakeup cause no one
* is waiting.
*/
if (vmp->vm_opcode == CODA_SIGNAL) {
CODA_FREE((caddr_t)vmp->vm_data,
(u_int)VC_IN_NO_DATA);
CODA_FREE((caddr_t)vmp, (u_int)sizeof(struct vmsg));
continue;
}
outstanding_upcalls++;
wakeup(&vmp->vm_sleep);
}
TAILQ_FOREACH(vmp, &vcp->vc_replies, vm_chain) {
outstanding_upcalls++;
wakeup(&vmp->vm_sleep);
}
MARK_VC_CLOSED(vcp);
if (outstanding_upcalls) {
#ifdef CODA_VERBOSE
printf("presleep: outstanding_upcalls = %d\n",
outstanding_upcalls);
#endif
(void) tsleep(&outstanding_upcalls, coda_call_sleep,
"coda_umount", 0);
#ifdef CODA_VERBOSE
printf("postsleep: outstanding_upcalls = %d\n",
outstanding_upcalls);
#endif
}
err = dounmount(mi->mi_vfsp, flag, td);
if (err)
myprintf(("Error %d unmounting vfs in vcclose(%s)\n", err,
devtoname(dev)));
return (0);
}
int
vc_read(struct cdev *dev, struct uio *uiop, int flag)
{
struct vcomm *vcp;
struct vmsg *vmp;
int error = 0;
ENTRY;
vcp = &dev2coda_mntinfo(dev)->mi_vcomm;
/*
* Get message at head of request queue.
*/
vmp = TAILQ_FIRST(&vcp->vc_requests);
if (vmp == NULL)
return (0); /* Nothing to read */
/*
* Move the input args into userspace.
*
* XXXRW: This is not safe in the presence of >1 reader, as vmp is
* still on the head of the list.
*/
uiop->uio_rw = UIO_READ;
error = uiomove(vmp->vm_data, vmp->vm_inSize, uiop);
if (error) {
myprintf(("vcread: error (%d) on uiomove\n", error));
error = EINVAL;
}
TAILQ_REMOVE(&vcp->vc_requests, vmp, vm_chain);
/*
* If request was a signal, free up the message and don't enqueue it
* in the reply queue.
*/
if (vmp->vm_opcode == CODA_SIGNAL) {
if (codadebug)
myprintf(("vcread: signal msg (%d, %d)\n",
vmp->vm_opcode, vmp->vm_unique));
CODA_FREE((caddr_t)vmp->vm_data, (u_int)VC_IN_NO_DATA);
CODA_FREE((caddr_t)vmp, (u_int)sizeof(struct vmsg));
return (error);
}
vmp->vm_flags |= VM_READ;
TAILQ_INSERT_TAIL(&vcp->vc_replies, vmp, vm_chain);
return (error);
}
int
vc_write(struct cdev *dev, struct uio *uiop, int flag)
{
struct vcomm *vcp;
struct vmsg *vmp;
struct coda_out_hdr *out;
u_long seq;
u_long opcode;
int buf[2];
int error = 0;
ENTRY;
vcp = &dev2coda_mntinfo(dev)->mi_vcomm;
/*
* Peek at the opcode, unique without transfering the data.
*/
uiop->uio_rw = UIO_WRITE;
error = uiomove((caddr_t)buf, sizeof(int) * 2, uiop);
if (error) {
myprintf(("vcwrite: error (%d) on uiomove\n", error));
return (EINVAL);
}
opcode = buf[0];
seq = buf[1];
if (codadebug)
myprintf(("vcwrite got a call for %ld.%ld\n", opcode, seq));
if (DOWNCALL(opcode)) {
union outputArgs pbuf;
/*
* Get the rest of the data.
*/
uiop->uio_rw = UIO_WRITE;
error = uiomove((caddr_t)&pbuf.coda_purgeuser.oh.result,
sizeof(pbuf) - (sizeof(int)*2), uiop);
if (error) {
myprintf(("vcwrite: error (%d) on uiomove (Op %ld "
"seq %ld)\n", error, opcode, seq));
return (EINVAL);
}
return (handleDownCall(dev2coda_mntinfo(dev), opcode, &pbuf));
}
/*
* Look for the message on the (waiting for) reply queue.
*/
TAILQ_FOREACH(vmp, &vcp->vc_replies, vm_chain) {
if (vmp->vm_unique == seq)
break;
}
if (vmp == NULL) {
if (codadebug)
myprintf(("vcwrite: msg (%ld, %ld) not found\n",
opcode, seq));
return (ESRCH);
}
/*
* Remove the message from the reply queue.
*/
TAILQ_REMOVE(&vcp->vc_replies, vmp, vm_chain);
/*
* Move data into response buffer.
*/
out = (struct coda_out_hdr *)vmp->vm_data;
/*
* Don't need to copy opcode and uniquifier.
*
* Get the rest of the data.
*/
if (vmp->vm_outSize < uiop->uio_resid) {
myprintf(("vcwrite: more data than asked for (%d < %zd)\n",
vmp->vm_outSize, uiop->uio_resid));
/*
* Notify caller of the error.
*/
wakeup(&vmp->vm_sleep);
return (EINVAL);
}
/*
* Save the value.
*/
buf[0] = uiop->uio_resid;
uiop->uio_rw = UIO_WRITE;
error = uiomove((caddr_t) &out->result, vmp->vm_outSize -
(sizeof(int) * 2), uiop);
if (error) {
myprintf(("vcwrite: error (%d) on uiomove (op %ld seq %ld)\n",
error, opcode, seq));
return (EINVAL);
}
/*
* I don't think these are used, but just in case.
*
* XXX - aren't these two already correct? -bnoble
*/
out->opcode = opcode;
out->unique = seq;
vmp->vm_outSize = buf[0]; /* Amount of data transferred? */
vmp->vm_flags |= VM_WRITE;
error = 0;
if (opcode == CODA_OPEN_BY_FD) {
struct coda_open_by_fd_out *tmp =
(struct coda_open_by_fd_out *)out;
struct file *fp;
struct vnode *vp = NULL;
if (tmp->oh.result == 0) {
error = getvnode(uiop->uio_td->td_proc->p_fd, CAP_WRITE,
tmp->fd, &fp);
if (!error) {
/*
* XXX: Since the whole driver runs with
* Giant, don't actually need to acquire it
* explicitly here yet.
*/
mtx_lock(&Giant);
vp = fp->f_vnode;
VREF(vp);
fdrop(fp, uiop->uio_td);
mtx_unlock(&Giant);
}
}
tmp->vp = vp;
}
wakeup(&vmp->vm_sleep);
return (error);
}
int
vc_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag,
struct thread *t)
{
ENTRY;
switch(cmd) {
case CODARESIZE:
return (ENODEV);
case CODASTATS:
return (ENODEV);
case CODAPRINT:
return (ENODEV);
case CIOC_KERNEL_VERSION:
switch (*(u_int *)addr) {
case 0:
*(u_int *)addr = coda_kernel_version;
return (0);
case 1:
case 2:
if (coda_kernel_version != *(u_int *)addr)
return (ENOENT);
else
return (0);
default:
return (ENOENT);
}
default:
return (EINVAL);
}
}
int
vc_poll(struct cdev *dev, int events, struct thread *td)
{
struct vcomm *vcp;
int event_msk = 0;
ENTRY;
vcp = &dev2coda_mntinfo(dev)->mi_vcomm;
event_msk = events & (POLLIN|POLLRDNORM);
if (!event_msk)
return (0);
if (!TAILQ_EMPTY(&vcp->vc_requests))
return (events & (POLLIN|POLLRDNORM));
selrecord(td, &(vcp->vc_selproc));
return (0);
}
/*
* Statistics.
*/
struct coda_clstat coda_clstat;
/*
* Key question: whether to sleep interuptably or uninteruptably when waiting
* for Venus. The former seems better (cause you can ^C a job), but then
* GNU-EMACS completion breaks. Use tsleep with no timeout, and no longjmp
* happens. But, when sleeping "uninterruptibly", we don't get told if it
* returns abnormally (e.g. kill -9).
*/
int
coda_call(struct coda_mntinfo *mntinfo, int inSize, int *outSize,
caddr_t buffer)
{
struct vcomm *vcp;
struct vmsg *vmp;
int error;
#ifdef CTL_C
struct thread *td = curthread;
struct proc *p = td->td_proc;
sigset_t psig_omask;
sigset_t tempset;
int i;
#endif
/*
* Unlikely, but could be a race condition with a dying warden.
*/
if (mntinfo == NULL)
return ENODEV;
vcp = &(mntinfo->mi_vcomm);
coda_clstat.ncalls++;
coda_clstat.reqs[((struct coda_in_hdr *)buffer)->opcode]++;
if (!VC_OPEN(vcp))
return (ENODEV);
CODA_ALLOC(vmp,struct vmsg *,sizeof(struct vmsg));
/*
* Format the request message.
*/
vmp->vm_data = buffer;
vmp->vm_flags = 0;
vmp->vm_inSize = inSize;
vmp->vm_outSize
= *outSize ? *outSize : inSize; /* |buffer| >= inSize */
vmp->vm_opcode = ((struct coda_in_hdr *)buffer)->opcode;
vmp->vm_unique = ++vcp->vc_seq;
if (codadebug)
myprintf(("Doing a call for %d.%d\n", vmp->vm_opcode,
vmp->vm_unique));
/*
* Fill in the common input args.
*/
((struct coda_in_hdr *)buffer)->unique = vmp->vm_unique;
/*
* Append msg to request queue and poke Venus.
*/
TAILQ_INSERT_TAIL(&vcp->vc_requests, vmp, vm_chain);
selwakeuppri(&(vcp->vc_selproc), coda_call_sleep);
/*
* We can be interrupted while we wait for Venus to process our
* request. If the interrupt occurs before Venus has read the
* request, we dequeue and return. If it occurs after the read but
* before the reply, we dequeue, send a signal message, and return.
* If it occurs after the reply we ignore it. In no case do we want
* to restart the syscall. If it was interrupted by a venus shutdown
* (vcclose), return ENODEV.
*
* Ignore return, we have to check anyway.
*/
#ifdef CTL_C
/*
* This is work in progress. Setting coda_pcatch lets tsleep
* reawaken on a ^c or ^z. The problem is that emacs sets certain
* interrupts as SA_RESTART. This means that we should exit sleep
* handle the "signal" and then go to sleep again. Mostly this is
* done by letting the syscall complete and be restarted. We are not
* idempotent and can not do this. A better solution is necessary.
*/
i = 0;
PROC_LOCK(p);
psig_omask = td->td_sigmask;
do {
error = msleep(&vmp->vm_sleep, &p->p_mtx,
(coda_call_sleep|coda_pcatch), "coda_call", hz*2);
if (error == 0)
break;
else if (error == EWOULDBLOCK) {
#ifdef CODA_VERBOSE
printf("coda_call: tsleep TIMEOUT %d sec\n", 2+2*i);
#endif
}
else {
SIGEMPTYSET(tempset);
SIGADDSET(tempset, SIGIO);
if (SIGSETEQ(td->td_siglist, tempset)) {
SIGADDSET(td->td_sigmask, SIGIO);
#ifdef CODA_VERBOSE
printf("coda_call: tsleep returns %d SIGIO, "
"cnt %d\n", error, i);
#endif
} else {
SIGDELSET(tempset, SIGIO);
SIGADDSET(tempset, SIGALRM);
if (SIGSETEQ(td->td_siglist, tempset)) {
SIGADDSET(td->td_sigmask, SIGALRM);
#ifdef CODA_VERBOSE
printf("coda_call: tsleep returns "
"%d SIGALRM, cnt %d\n", error, i);
#endif
} else {
#ifdef CODA_VERBOSE
printf("coda_call: tsleep returns "
"%d, cnt %d\n", error, i);
#endif
#ifdef notyet
tempset = td->td_siglist;
SIGSETNAND(tempset, td->td_sigmask);
printf("coda_call: siglist = %p, "
"sigmask = %p, mask %p\n",
td->td_siglist, td->td_sigmask,
tempset);
break;
SIGSETOR(td->td_sigmask, td->td_siglist);
tempset = td->td_siglist;
SIGSETNAND(tempset, td->td_sigmask);
printf("coda_call: new mask, "
"siglist = %p, sigmask = %p, "
"mask %p\n", td->td_siglist,
td->td_sigmask, tempset);
#endif
}
}
}
} while (error && i++ < 128 && VC_OPEN(vcp));
td->td_sigmask = psig_omask;
signotify(td);
PROC_UNLOCK(p);
#else
(void)tsleep(&vmp->vm_sleep, coda_call_sleep, "coda_call", 0);
#endif
if (VC_OPEN(vcp)) {
/*
* Venus is still alive.
*
* Op went through, interrupt or not...
*/
if (vmp->vm_flags & VM_WRITE) {
error = 0;
*outSize = vmp->vm_outSize;
} else if (!(vmp->vm_flags & VM_READ)) {
/* Interrupted before venus read it. */
#ifdef CODA_VERBOSE
if (1)
#else
if (codadebug)
#endif
myprintf(("interrupted before read: op = "
"%d.%d, flags = %x\n", vmp->vm_opcode,
vmp->vm_unique, vmp->vm_flags));
TAILQ_REMOVE(&vcp->vc_requests, vmp, vm_chain);
error = EINTR;
} else {
/*
* (!(vmp->vm_flags & VM_WRITE)) means interrupted
* after upcall started.
*
* Interrupted after start of upcall, send venus a
* signal.
*/
struct coda_in_hdr *dog;
struct vmsg *svmp;
#ifdef CODA_VERBOSE
if (1)
#else
if (codadebug)
#endif
myprintf(("Sending Venus a signal: op = "
"%d.%d, flags = %x\n", vmp->vm_opcode,
vmp->vm_unique, vmp->vm_flags));
TAILQ_REMOVE(&vcp->vc_requests, vmp, vm_chain);
error = EINTR;
CODA_ALLOC(svmp, struct vmsg *, sizeof(struct vmsg));
CODA_ALLOC((svmp->vm_data), char *,
sizeof(struct coda_in_hdr));
dog = (struct coda_in_hdr *)svmp->vm_data;
svmp->vm_flags = 0;
dog->opcode = svmp->vm_opcode = CODA_SIGNAL;
dog->unique = svmp->vm_unique = vmp->vm_unique;
svmp->vm_inSize = sizeof (struct coda_in_hdr);
/*??? rvb */ svmp->vm_outSize = sizeof (struct coda_in_hdr);
if (codadebug)
myprintf(("coda_call: enqueing signal msg "
"(%d, %d)\n", svmp->vm_opcode,
svmp->vm_unique));
/*
* Insert at head of queue!
*
* XXXRW: Actually, the tail.
*/
TAILQ_INSERT_TAIL(&vcp->vc_requests, svmp, vm_chain);
selwakeuppri(&(vcp->vc_selproc), coda_call_sleep);
}
} else {
/* If venus died (!VC_OPEN(vcp)) */
if (codadebug)
myprintf(("vcclose woke op %d.%d flags %d\n",
vmp->vm_opcode, vmp->vm_unique, vmp->vm_flags));
error = ENODEV;
}
CODA_FREE(vmp, sizeof(struct vmsg));
if (outstanding_upcalls > 0 && (--outstanding_upcalls == 0))
wakeup(&outstanding_upcalls);
if (!error)
error = ((struct coda_out_hdr *)buffer)->result;
return (error);
}

View File

@ -1,46 +0,0 @@
/*-
*
* Coda: an Experimental Distributed File System
* Release 3.1
*
* Copyright (c) 1998 Carnegie Mellon University
* All Rights Reserved
*
* Permission to use, copy, modify and distribute this software and its
* documentation is hereby granted, provided that both the copyright
* notice and this permission notice appear in all copies of the
* software, derivative works or modified versions, and any portions
* thereof, and that both notices appear in supporting documentation, and
* that credit is given to Carnegie Mellon University in all documents
* and publicity pertaining to direct or indirect use of this code or its
* derivatives.
*
* CODA IS AN EXPERIMENTAL SOFTWARE SYSTEM AND IS KNOWN TO HAVE BUGS,
* SOME OF WHICH MAY HAVE SERIOUS CONSEQUENCES. CARNEGIE MELLON ALLOWS
* FREE USE OF THIS SOFTWARE IN ITS "AS IS" CONDITION. CARNEGIE MELLON
* DISCLAIMS ANY LIABILITY OF ANY KIND FOR ANY DAMAGES WHATSOEVER
* RESULTING DIRECTLY OR INDIRECTLY FROM THE USE OF THIS SOFTWARE OR OF
* ANY DERIVATIVE WORK.
*
* Carnegie Mellon encourages users of this software to return any
* improvements or extensions that they make, and to grant Carnegie
* Mellon the rights to redistribute these changes without encumbrance.
*
* @(#) src/sys/coda/coda_psdev.c,v 1.1.1.1 1998/08/29 21:14:52 rvb Exp $
* $FreeBSD$
*/
#ifndef _CODA_PSDEV_H_
#define _CODA_PSDEV_H_
/*
* Prototypes for cfs device operations.
*/
d_open_t vc_open;
d_close_t vc_close;
d_read_t vc_read;
d_write_t vc_write;
d_ioctl_t vc_ioctl;
d_poll_t vc_poll;
#endif /* !_CODA_PSDEV_H_ */

View File

@ -1,628 +0,0 @@
/*-
* Coda: an Experimental Distributed File System
* Release 3.1
*
* Copyright (c) 1987-1998 Carnegie Mellon University
* All Rights Reserved
*
* Permission to use, copy, modify and distribute this software and its
* documentation is hereby granted, provided that both the copyright
* notice and this permission notice appear in all copies of the
* software, derivative works or modified versions, and any portions
* thereof, and that both notices appear in supporting documentation, and
* that credit is given to Carnegie Mellon University in all documents
* and publicity pertaining to direct or indirect use of this code or its
* derivatives.
*
* CODA IS AN EXPERIMENTAL SOFTWARE SYSTEM AND IS KNOWN TO HAVE BUGS,
* SOME OF WHICH MAY HAVE SERIOUS CONSEQUENCES. CARNEGIE MELLON ALLOWS
* FREE USE OF THIS SOFTWARE IN ITS "AS IS" CONDITION. CARNEGIE MELLON
* DISCLAIMS ANY LIABILITY OF ANY KIND FOR ANY DAMAGES WHATSOEVER
* RESULTING DIRECTLY OR INDIRECTLY FROM THE USE OF THIS SOFTWARE OR OF
* ANY DERIVATIVE WORK.
*
* Carnegie Mellon encourages users of this software to return any
* improvements or extensions that they make, and to grant Carnegie
* Mellon the rights to redistribute these changes without encumbrance.
*
* @(#) src/sys/coda/coda_subr.c,v 1.1.1.1 1998/08/29 21:14:52 rvb Exp $
*/
/*-
* Mach Operating System
* Copyright (c) 1989 Carnegie-Mellon University
* All rights reserved. The CMU software License Agreement specifies
* the terms and conditions for use and redistribution.
*/
/*
* This code was written for the Coda filesystem at Carnegie Mellon
* University. Contributers include David Steere, James Kistler, and
* M. Satyanarayanan.
*/
/*-
* NOTES: rvb
* 1. Added coda_unmounting to mark all cnodes as being UNMOUNTING. This
* has to be done before dounmount is called. Because some of the
* routines that dounmount calls before coda_unmounted might try to
* force flushes to venus. The vnode pager does this.
* 2. coda_unmounting marks all cnodes scanning coda_cache.
* 3. cfs_checkunmounting (under DEBUG) checks all cnodes by chasing the
* vnodes under the /coda mount point.
* 4. coda_cacheprint (under DEBUG) prints names with vnode/cnode address.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/lock.h>
#include <sys/malloc.h>
#include <sys/mutex.h>
#include <sys/mount.h>
#include <fs/coda/coda.h>
#include <fs/coda/cnode.h>
#include <fs/coda/coda_subr.h>
static int coda_active = 0;
static int coda_reuse = 0;
static int coda_new = 0;
static struct cnode *coda_freelist = NULL;
static struct cnode *coda_cache[CODA_CACHESIZE];
#define CNODE_NEXT(cp) ((cp)->c_next)
#ifdef CODA_COMPAT_5
#define coda_hash(fid) (((fid)->Volume + (fid)->Vnode) & (CODA_CACHESIZE-1))
#define IS_DIR(cnode) (cnode.Vnode & 0x1)
#else
#define coda_hash(fid) (coda_f2i(fid) & (CODA_CACHESIZE-1))
#define IS_DIR(cnode) (cnode.opaque[2] & 0x1)
#endif
/*
* Allocate a cnode.
*/
struct cnode *
coda_alloc(void)
{
struct cnode *cp;
if (coda_freelist != NULL) {
cp = coda_freelist;
coda_freelist = CNODE_NEXT(cp);
coda_reuse++;
} else {
CODA_ALLOC(cp, struct cnode *, sizeof(struct cnode));
/*
* FreeBSD vnodes don't have any Pager info in them ('cause
* there are no external pagers, duh!).
*/
#define VNODE_VM_INFO_INIT(vp) /* MT */
VNODE_VM_INFO_INIT(CTOV(cp));
coda_new++;
}
bzero(cp, sizeof (struct cnode));
return (cp);
}
/*
* Deallocate a cnode.
*/
void
coda_free(struct cnode *cp)
{
CNODE_NEXT(cp) = coda_freelist;
coda_freelist = cp;
}
/*
* Put a cnode in the hash table.
*/
void
coda_save(struct cnode *cp)
{
CNODE_NEXT(cp) = coda_cache[coda_hash(&cp->c_fid)];
coda_cache[coda_hash(&cp->c_fid)] = cp;
}
/*
* Remove a cnode from the hash table.
*/
void
coda_unsave(struct cnode *cp)
{
struct cnode *ptr;
struct cnode *ptrprev = NULL;
ptr = coda_cache[coda_hash(&cp->c_fid)];
while (ptr != NULL) {
if (ptr == cp) {
if (ptrprev == NULL)
coda_cache[coda_hash(&cp->c_fid)] =
CNODE_NEXT(ptr);
else
CNODE_NEXT(ptrprev) = CNODE_NEXT(ptr);
CNODE_NEXT(cp) = (struct cnode *)NULL;
return;
}
ptrprev = ptr;
ptr = CNODE_NEXT(ptr);
}
}
/*
* Lookup a cnode by fid. If the cnode is dying, it is bogus so skip it.
*
* NOTE: this allows multiple cnodes with same fid -- dcs 1/25/95
*/
struct cnode *
coda_find(struct CodaFid *fid)
{
struct cnode *cp;
cp = coda_cache[coda_hash(fid)];
while (cp) {
if (coda_fid_eq(&(cp->c_fid), fid) && (!IS_UNMOUNTING(cp))) {
coda_active++;
return (cp);
}
cp = CNODE_NEXT(cp);
}
return (NULL);
}
/*
* Clear all cached access control decisions from Coda.
*/
static void
coda_acccache_purge(struct mount *mnt)
{
struct cnode *cp;
int hash;
for (hash = 0; hash < CODA_CACHESIZE; hash++) {
for (cp = coda_cache[hash]; cp != NULL;
cp = CNODE_NEXT(cp)) {
if (CTOV(cp)->v_mount == mnt && VALID_ACCCACHE(cp)) {
CODADEBUG(CODA_FLUSH, myprintf(("acccache "
"purge fid %s uid %d mode 0x%x\n",
coda_f2s(&cp->c_fid), cp->c_cached_uid,
(int)cp->c_cached_mode)););
cp->c_flags &= ~C_ACCCACHE;
}
}
}
}
/*
* When a user loses their tokens (or other related events), we invalidate
* any cached access rights in the access cache. In the Linux version of
* Coda, we maintain a global epoch and simply bump it to invalidate all
* cached results generated in the epoch. For now, we walk all cnodes and
* manually invalidate just that uid in FreeBSD.
*/
static void
coda_acccache_purgeuser(struct mount *mnt, uid_t uid)
{
struct cnode *cp;
int hash;
for (hash = 0; hash < CODA_CACHESIZE; hash++) {
for (cp = coda_cache[hash]; cp != NULL;
cp = CNODE_NEXT(cp)) {
if (CTOV(cp)->v_mount == mnt &&
VALID_ACCCACHE(cp) && (cp->c_cached_uid == uid)) {
CODADEBUG(CODA_PURGEUSER, myprintf((
"acccache purgeuser fid %s uid %d mode "
"0x%x\n", coda_f2s(&cp->c_fid),
cp->c_cached_uid, (int)cp->c_cached_mode)););
cp->c_flags &= ~C_ACCCACHE;
}
}
}
}
/*
* coda_kill is called as a side effect to vcopen. To prevent any cnodes
* left around from an earlier run of a venus or warden from causing problems
* with the new instance, mark any outstanding cnodes as dying. Future
* operations on these cnodes should fail (excepting coda_inactive of
* course!). Since multiple venii/wardens can be running, only kill the
* cnodes for a particular entry in the coda_mnttbl. -- DCS 12/1/94
*
* XXX: I don't believe any special behavior is required with respect to the
* global namecache here, as /coda will have unmounted and hence cache_flush
* will have run...?
*/
int
coda_kill(struct mount *whoIam, enum dc_status dcstat)
{
int hash, count = 0;
struct cnode *cp;
/*-
* Algorithm is as follows:
* Second, flush whatever vnodes we can from the name cache.
*
* Finally, step through whatever is left and mark them dying.
* This prevents any operation at all.
*
* This is slightly overkill, but should work. Eventually it'd be
* nice to only flush those entries from the namecache that reference
* a vnode in this vfs.
*
* XXXRW: Perhaps we no longer need to purge the name cache when
* using the VFS name cache, as unmount will do that.
*/
cache_purgevfs(whoIam);
for (hash = 0; hash < CODA_CACHESIZE; hash++) {
for (cp = coda_cache[hash];cp != NULL;
cp = CNODE_NEXT(cp)) {
if (CTOV(cp)->v_mount == whoIam) {
#ifdef DEBUG
printf("coda_kill: vp %p, cp %p\n", CTOV(cp),
cp);
#endif
count++;
CODADEBUG(CODA_FLUSH, myprintf(("Live cnode "
"fid %s flags %d count %d\n",
coda_f2s(&cp->c_fid), cp->c_flags,
vrefcnt(CTOV(cp)))););
}
}
}
return (count);
}
/*
* There are two reasons why a cnode may be in use, it may be in the name
* cache or it may be executing.
*/
void
coda_flush(struct coda_mntinfo *mnt, enum dc_status dcstat)
{
int hash;
struct cnode *cp;
coda_clstat.ncalls++;
coda_clstat.reqs[CODA_FLUSH]++;
coda_acccache_purge(mnt->mi_vfsp);
cache_purgevfs(mnt->mi_vfsp);
for (hash = 0; hash < CODA_CACHESIZE; hash++) {
for (cp = coda_cache[hash]; cp != NULL;
cp = CNODE_NEXT(cp)) {
/*
* Only files that can be executed need to be flushed
* from the VM.
*
* NOTE: Currently this doesn't do anything, but
* perhaps it should?
*/
if (!IS_DIR(cp->c_fid))
coda_vmflush(cp);
}
}
}
/*
* As a debugging measure, print out any cnodes that lived through a name
* cache flush.
*/
void
coda_testflush(void)
{
int hash;
struct cnode *cp;
for (hash = 0; hash < CODA_CACHESIZE; hash++) {
for (cp = coda_cache[hash]; cp != NULL;
cp = CNODE_NEXT(cp))
myprintf(("Live cnode fid %s count %d\n",
coda_f2s(&cp->c_fid), CTOV(cp)->v_usecount));
}
}
/*
* First, step through all cnodes and mark them unmounting. FreeBSD kernels
* may try to fsync them now that venus is dead, which would be a bad thing.
*/
void
coda_unmounting(struct mount *whoIam)
{
int hash;
struct cnode *cp;
for (hash = 0; hash < CODA_CACHESIZE; hash++) {
for (cp = coda_cache[hash]; cp != NULL;
cp = CNODE_NEXT(cp)) {
if (CTOV(cp)->v_mount == whoIam) {
if (cp->c_flags & (C_LOCKED|C_WANTED)) {
printf("coda_unmounting: Unlocking "
"%p\n", cp);
cp->c_flags &= ~(C_LOCKED|C_WANTED);
wakeup((caddr_t) cp);
}
cp->c_flags |= C_UNMOUNTING;
}
}
}
}
#ifdef DEBUG
void
coda_checkunmounting(struct mount *mp)
{
struct vnode *vp, *nvp;
struct cnode *cp;
int count = 0, bad = 0;
MNT_VNODE_FOREACH_ALL(vp, mp, nvp) {
cp = VTOC(vp);
count++;
if (!(cp->c_flags & C_UNMOUNTING)) {
bad++;
printf("vp %p, cp %p missed\n", vp, cp);
cp->c_flags |= C_UNMOUNTING;
}
VI_UNLOCK(vp);
}
}
void
coda_cacheprint(struct mount *whoIam)
{
int hash;
struct cnode *cp;
int count = 0;
printf("coda_cacheprint: coda_ctlvp %p, cp %p", coda_ctlvp,
VTOC(coda_ctlvp));
#if 0
coda_nc_name(VTOC(coda_ctlvp));
#endif
printf("\n");
for (hash = 0; hash < CODA_CACHESIZE; hash++) {
for (cp = coda_cache[hash]; cp != NULL;
cp = CNODE_NEXT(cp)) {
if (CTOV(cp)->v_mount == whoIam) {
printf("coda_cacheprint: vp %p, cp %p",
CTOV(cp), cp);
#if 0
coda_nc_name(cp);
#endif
printf("\n");
count++;
}
}
}
printf("coda_cacheprint: count %d\n", count);
}
#endif
/*-
* There are 6 cases where invalidations occur. The semantics of each is
* listed here:
*
* CODA_FLUSH -- Flush all entries from the name cache and the cnode
* cache.
*
* CODA_PURGEUSER -- Flush all entries from the name cache for a specific
* user. This call is a result of token expiration.
*
* The next two are the result of callbacks on a file or directory:
*
* CODA_ZAPDIR -- Flush the attributes for the dir from its cnode. Zap
* all children of this directory from the namecache.
*
* CODA_ZAPFILE -- Flush the attributes for a file.
*
* The fifth is a result of Venus detecting an inconsistent file:
*
* CODA_PURGEFID -- Flush the attribute for the file; if it is a dir (odd
* vnode), purge its children from the namecache; remove
* the file from the namecache.
*
* The sixth allows Venus to replace local fids with global ones during
* reintegration.
*
* CODA_REPLACE -- Replace one CodaFid with another throughout the name
* cache.
*/
int
handleDownCall(struct coda_mntinfo *mnt, int opcode, union outputArgs *out)
{
int error;
/*
* Handle invalidate requests.
*/
switch (opcode) {
case CODA_FLUSH: {
coda_flush(mnt, IS_DOWNCALL);
/* Print any remaining cnodes. */
CODADEBUG(CODA_FLUSH, coda_testflush(););
return (0);
}
case CODA_PURGEUSER: {
coda_clstat.ncalls++;
coda_clstat.reqs[CODA_PURGEUSER]++;
/* XXX - need to prevent fsync's. */
/*
* Purge any access cache entries for the uid.
*/
#ifdef CODA_COMPAT_5
coda_acccache_purgeuser(mnt->mi_vfsp,
out->coda_purgeuser.cred.cr_uid);
#else
coda_acccache_purgeuser(mnt->mi_vfsp,
out->coda_purgeuser.uid);
#endif
return (0);
}
case CODA_ZAPFILE: {
struct cnode *cp;
error = 0;
coda_clstat.ncalls++;
coda_clstat.reqs[CODA_ZAPFILE]++;
cp = coda_find(&out->coda_zapfile.Fid);
if (cp != NULL) {
vref(CTOV(cp));
cache_purge(CTOV(cp));
cp->c_flags &= ~(C_VATTR | C_ACCCACHE);
ASSERT_VOP_LOCKED(CTOV(cp), "coda HandleDownCall");
if (VOP_IS_TEXT(CTOV(cp)))
error = coda_vmflush(cp);
CODADEBUG(CODA_ZAPFILE,
myprintf(("zapfile: fid = %s, refcnt = %d, error = "
"%d\n", coda_f2s(&cp->c_fid),
CTOV(cp)->v_usecount - 1, error)););
if (vrefcnt(CTOV(cp)) == 1)
cp->c_flags |= C_PURGING;
vrele(CTOV(cp));
}
return (error);
}
case CODA_ZAPDIR: {
struct cnode *cp;
coda_clstat.ncalls++;
coda_clstat.reqs[CODA_ZAPDIR]++;
cp = coda_find(&out->coda_zapdir.Fid);
if (cp != NULL) {
vref(CTOV(cp));
cache_purge(CTOV(cp));
cp->c_flags &= ~(C_VATTR | C_ACCCACHE);
CODADEBUG(CODA_ZAPDIR, myprintf(("zapdir: fid = %s, "
"refcnt = %d\n", coda_f2s(&cp->c_fid),
CTOV(cp)->v_usecount - 1)););
if (vrefcnt(CTOV(cp)) == 1)
cp->c_flags |= C_PURGING;
vrele(CTOV(cp));
}
return (0);
}
case CODA_PURGEFID: {
struct cnode *cp;
error = 0;
coda_clstat.ncalls++;
coda_clstat.reqs[CODA_PURGEFID]++;
cp = coda_find(&out->coda_purgefid.Fid);
if (cp != NULL) {
vref(CTOV(cp));
cache_purge(CTOV(cp));
cp->c_flags &= ~(C_VATTR | C_ACCCACHE);
ASSERT_VOP_LOCKED(CTOV(cp), "coda HandleDownCall");
if (!(IS_DIR(out->coda_purgefid.Fid))
&& VOP_IS_TEXT(CTOV(cp)))
error = coda_vmflush(cp);
CODADEBUG(CODA_PURGEFID, myprintf(("purgefid: fid "
"= %s, refcnt = %d, error = %d\n",
coda_f2s(&cp->c_fid),
CTOV(cp)->v_usecount - 1, error)););
if (vrefcnt(CTOV(cp)) == 1)
cp->c_flags |= C_PURGING;
vrele(CTOV(cp));
}
return (error);
}
case CODA_REPLACE: {
struct cnode *cp = NULL;
coda_clstat.ncalls++;
coda_clstat.reqs[CODA_REPLACE]++;
cp = coda_find(&out->coda_replace.OldFid);
if (cp != NULL) {
/*
* Remove the cnode from the hash table, replace the
* fid, and reinsert. Clear the attribute cache as
* the "inode number" may have changed (it's just a
* hash of the fid, and the fid is changing).
*/
vref(CTOV(cp));
coda_unsave(cp);
cp->c_fid = out->coda_replace.NewFid;
cp->c_flags &= ~C_VATTR;
coda_save(cp);
CODADEBUG(CODA_REPLACE, myprintf(("replace: oldfid "
"= %s, newfid = %s, cp = %p\n",
coda_f2s(&out->coda_replace.OldFid),
coda_f2s(&cp->c_fid), cp)););
vrele(CTOV(cp));
}
return (0);
}
default:
myprintf(("handleDownCall: unknown opcode %d\n", opcode));
return (EINVAL);
}
}
int
coda_vmflush(struct cnode *cp)
{
return (0);
}
/*
* Kernel-internal debugging switches.
*/
void
coda_debugon(void)
{
codadebug = -1;
coda_vnop_print_entry = 1;
coda_psdev_print_entry = 1;
coda_vfsop_print_entry = 1;
}
void
coda_debugoff(void)
{
codadebug = 0;
coda_vnop_print_entry = 0;
coda_psdev_print_entry = 0;
coda_vfsop_print_entry = 0;
}
/*-
* Utilities used by both client and server
* Standard levels:
* 0) no debugging
* 1) hard failures
* 2) soft failures
* 3) current test software
* 4) main procedure entry points
* 5) main procedure exit points
* 6) utility procedure entry points
* 7) utility procedure exit points
* 8) obscure procedure entry points
* 9) obscure procedure exit points
* 10) random stuff
* 11) all <= 1
* 12) all <= 2
* 13) all <= 3
* ...
*/

View File

@ -1,49 +0,0 @@
/*-
*
* Coda: an Experimental Distributed File System
* Release 3.1
*
* Copyright (c) 1987-1998 Carnegie Mellon University
* All Rights Reserved
*
* Permission to use, copy, modify and distribute this software and its
* documentation is hereby granted, provided that both the copyright
* notice and this permission notice appear in all copies of the
* software, derivative works or modified versions, and any portions
* thereof, and that both notices appear in supporting documentation, and
* that credit is given to Carnegie Mellon University in all documents
* and publicity pertaining to direct or indirect use of this code or its
* derivatives.
*
* CODA IS AN EXPERIMENTAL SOFTWARE SYSTEM AND IS KNOWN TO HAVE BUGS,
* SOME OF WHICH MAY HAVE SERIOUS CONSEQUENCES. CARNEGIE MELLON ALLOWS
* FREE USE OF THIS SOFTWARE IN ITS "AS IS" CONDITION. CARNEGIE MELLON
* DISCLAIMS ANY LIABILITY OF ANY KIND FOR ANY DAMAGES WHATSOEVER
* RESULTING DIRECTLY OR INDIRECTLY FROM THE USE OF THIS SOFTWARE OR OF
* ANY DERIVATIVE WORK.
*
* Carnegie Mellon encourages users of this software to return any
* improvements or extensions that they make, and to grant Carnegie
* Mellon the rights to redistribute these changes without encumbrance.
*
* @(#) src/sys/coda/coda_subr.h,v 1.1.1.1 1998/08/29 21:14:52 rvb Exp $
* $FreeBSD$
*/
#ifndef _CODA_SUBR_H_
#define _CODA_SUBR_H_
struct cnode *coda_alloc(void);
void coda_free(struct cnode *cp);
struct cnode *coda_find(struct CodaFid *fid);
void coda_flush(struct coda_mntinfo *mnt, enum dc_status dcstat);
void coda_testflush(void);
void coda_checkunmounting(struct mount *mp);
void coda_cacheprint(struct mount *whoIam);
void coda_debugon(void);
void coda_debugoff(void);
int coda_kill(struct mount *whoIam, enum dc_status dcstat);
void coda_save(struct cnode *cp);
void coda_unsave(struct cnode *cp);
#endif /* !_CODA_SUBR_H_ */

View File

@ -1,705 +0,0 @@
/*-
* Coda: an Experimental Distributed File System
* Release 3.1
*
* Copyright (c) 1987-1998 Carnegie Mellon University
* All Rights Reserved
*
* Permission to use, copy, modify and distribute this software and its
* documentation is hereby granted, provided that both the copyright
* notice and this permission notice appear in all copies of the
* software, derivative works or modified versions, and any portions
* thereof, and that both notices appear in supporting documentation, and
* that credit is given to Carnegie Mellon University in all documents
* and publicity pertaining to direct or indirect use of this code or its
* derivatives.
*
* CODA IS AN EXPERIMENTAL SOFTWARE SYSTEM AND IS KNOWN TO HAVE BUGS,
* SOME OF WHICH MAY HAVE SERIOUS CONSEQUENCES. CARNEGIE MELLON ALLOWS
* FREE USE OF THIS SOFTWARE IN ITS "AS IS" CONDITION. CARNEGIE MELLON
* DISCLAIMS ANY LIABILITY OF ANY KIND FOR ANY DAMAGES WHATSOEVER
* RESULTING DIRECTLY OR INDIRECTLY FROM THE USE OF THIS SOFTWARE OR OF
* ANY DERIVATIVE WORK.
*
* Carnegie Mellon encourages users of this software to return any
* improvements or extensions that they make, and to grant Carnegie
* Mellon the rights to redistribute these changes without encumbrance.
*
* @(#) src/sys/cfs/coda_venus.c,v 1.1.1.1 1998/08/29 21:14:52 rvb Exp $
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/fcntl.h>
#include <sys/ioccom.h>
#include <sys/lock.h>
#include <sys/malloc.h>
#include <sys/mutex.h>
#include <sys/proc.h>
#include <sys/sx.h>
#include <fs/coda/coda.h>
#include <fs/coda/cnode.h>
#include <fs/coda/coda_venus.h>
#include <fs/coda/coda_pioctl.h>
#define DECL_NO_IN(name) \
struct coda_in_hdr *inp; \
struct name ## _out *outp; \
int name ## _size = sizeof (struct coda_in_hdr); \
int Isize = sizeof (struct coda_in_hdr); \
int Osize = sizeof (struct name ## _out); \
int error
#define DECL(name) \
struct name ## _in *inp; \
struct name ## _out *outp; \
int name ## _size = sizeof (struct name ## _in); \
int Isize = sizeof (struct name ## _in); \
int Osize = sizeof (struct name ## _out); \
int error
#define DECL_NO_OUT(name) \
struct name ## _in *inp; \
struct coda_out_hdr *outp; \
int name ## _size = sizeof (struct name ## _in); \
int Isize = sizeof (struct name ## _in); \
int Osize = sizeof (struct coda_out_hdr); \
int error
#define ALLOC_NO_IN(name) \
if (Osize > name ## _size) \
name ## _size = Osize; \
CODA_ALLOC(inp, struct coda_in_hdr *, name ## _size); \
outp = (struct name ## _out *) inp
#define ALLOC(name) \
if (Osize > name ## _size) \
name ## _size = Osize; \
CODA_ALLOC(inp, struct name ## _in *, name ## _size); \
outp = (struct name ## _out *) inp
#define ALLOC_NO_OUT(name) \
if (Osize > name ## _size) \
name ## _size = Osize; \
CODA_ALLOC(inp, struct name ## _in *, name ## _size); \
outp = (struct coda_out_hdr *) inp
#define STRCPY(struc, name, len) \
bcopy(name, (char *)inp + (int)inp->struc, len); \
((char*)inp + (int)inp->struc)[len++] = 0; \
Isize += len
#ifdef CODA_COMPAT_5
#define INIT_IN(in, op, ident, p) do { \
(in)->opcode = (op); \
sx_slock(&proctree_lock); \
(in)->pid = p ? p->p_pid : -1; \
(in)->pgid = p ? p->p_pgid : -1; \
(in)->sid = (p && p->p_session && p->p_session->s_leader) ? \
(p->p_session->s_leader->p_pid) : -1; \
sx_sunlock(&proctree_lock); \
if (ident != NOCRED) { \
(in)->cred.cr_uid = ident->cr_uid; \
(in)->cred.cr_groupid = ident->cr_gid; \
} else { \
bzero(&((in)->cred),sizeof(struct coda_cred)); \
(in)->cred.cr_uid = -1; \
(in)->cred.cr_groupid = -1; \
} \
} while (0)
#else
#define INIT_IN(in, op, ident, p) do { \
(in)->opcode = (op); \
(in)->pid = p ? p->p_pid : -1; \
(in)->pgid = p ? p->p_pgid : -1; \
if (ident != NOCRED) \
(in)->uid = ident->cr_uid; \
else \
(in)->uid = -1; \
} while (0)
#endif
#define CNV_OFLAG(to, from) do { \
to = 0; \
if (from & FREAD) to |= C_O_READ; \
if (from & FWRITE) to |= C_O_WRITE; \
if (from & O_TRUNC) to |= C_O_TRUNC; \
if (from & O_EXCL) to |= C_O_EXCL; \
if (from & O_CREAT) to |= C_O_CREAT; \
} while (0)
#define CNV_VV2V_ATTR(top, fromp) do { \
(top)->va_type = (fromp)->va_type; \
(top)->va_mode = (fromp)->va_mode; \
(top)->va_nlink = (fromp)->va_nlink; \
(top)->va_uid = (fromp)->va_uid; \
(top)->va_gid = (fromp)->va_gid; \
(top)->va_fsid = VNOVAL; \
(top)->va_fileid = (fromp)->va_fileid; \
(top)->va_size = (fromp)->va_size; \
(top)->va_blocksize = (fromp)->va_blocksize; \
(top)->va_atime = (fromp)->va_atime; \
(top)->va_mtime = (fromp)->va_mtime; \
(top)->va_ctime = (fromp)->va_ctime; \
(top)->va_gen = (fromp)->va_gen; \
(top)->va_flags = (fromp)->va_flags; \
(top)->va_rdev = (fromp)->va_rdev; \
(top)->va_bytes = (fromp)->va_bytes; \
(top)->va_filerev = (fromp)->va_filerev; \
(top)->va_vaflags = VNOVAL; \
(top)->va_spare = VNOVAL; \
} while (0)
#define CNV_V2VV_ATTR(top, fromp) do { \
(top)->va_type = (fromp)->va_type; \
(top)->va_mode = (fromp)->va_mode; \
(top)->va_nlink = (fromp)->va_nlink; \
(top)->va_uid = (fromp)->va_uid; \
(top)->va_gid = (fromp)->va_gid; \
(top)->va_fileid = (fromp)->va_fileid; \
(top)->va_size = (fromp)->va_size; \
(top)->va_blocksize = (fromp)->va_blocksize; \
(top)->va_atime = (fromp)->va_atime; \
(top)->va_mtime = (fromp)->va_mtime; \
(top)->va_ctime = (fromp)->va_ctime; \
(top)->va_gen = (fromp)->va_gen; \
(top)->va_flags = (fromp)->va_flags; \
(top)->va_rdev = (fromp)->va_rdev; \
(top)->va_bytes = (fromp)->va_bytes; \
(top)->va_filerev = (fromp)->va_filerev; \
} while (0)
int coda_kernel_version = CODA_KERNEL_VERSION;
int
venus_root(void *mdp, struct ucred *cred, struct proc *p,
/*out*/ struct CodaFid *VFid)
{
DECL_NO_IN(coda_root); /* sets Isize & Osize */
ALLOC_NO_IN(coda_root); /* sets inp & outp */
/* send the open to venus. */
INIT_IN(inp, CODA_ROOT, cred, p);
error = coda_call(mdp, Isize, &Osize, (char *)inp);
if (!error)
*VFid = outp->Fid;
CODA_FREE(inp, coda_root_size);
return (error);
}
int
venus_open(void *mdp, struct CodaFid *fid, int flag, struct ucred *cred,
struct proc *p, /*out*/ struct vnode **vp)
{
int cflag;
DECL(coda_open_by_fd); /* sets Isize & Osize */
ALLOC(coda_open_by_fd); /* sets inp & outp */
/* send the open to venus. */
INIT_IN(&inp->ih, CODA_OPEN_BY_FD, cred, p);
inp->Fid = *fid;
CNV_OFLAG(cflag, flag);
inp->flags = cflag;
error = coda_call(mdp, Isize, &Osize, (char *)inp);
*vp = error ? NULL : outp->vp;
CODA_FREE(inp, coda_open_by_fd_size);
return (error);
}
int
venus_close(void *mdp, struct CodaFid *fid, int flag, struct ucred *cred,
struct proc *p)
{
int cflag;
DECL_NO_OUT(coda_close); /* sets Isize & Osize */
ALLOC_NO_OUT(coda_close); /* sets inp & outp */
INIT_IN(&inp->ih, CODA_CLOSE, cred, p);
inp->Fid = *fid;
CNV_OFLAG(cflag, flag);
inp->flags = cflag;
error = coda_call(mdp, Isize, &Osize, (char *)inp);
CODA_FREE(inp, coda_close_size);
return (error);
}
/*
* These two calls will not exist!!! The container file is read/written
* directly.
*/
void
venus_read(void)
{
}
void
venus_write(void)
{
}
/*
* This is a bit sad too. the ioctl's are for the control file, not for
* normal files.
*/
int
venus_ioctl(void *mdp, struct CodaFid *fid, int com, int flag, caddr_t data,
struct ucred *cred, struct proc *p)
{
DECL(coda_ioctl); /* sets Isize & Osize */
struct PioctlData *iap = (struct PioctlData *)data;
int tmp;
coda_ioctl_size = VC_MAXMSGSIZE;
ALLOC(coda_ioctl); /* sets inp & outp */
INIT_IN(&inp->ih, CODA_IOCTL, cred, p);
inp->Fid = *fid;
/*
* Command was mutated by increasing its size field to reflect the
* path and follow args. we need to subtract that out before sending
* the command to venus.
*/
inp->cmd = (com & ~(IOCPARM_MASK << 16));
tmp = ((com >> 16) & IOCPARM_MASK) - sizeof (char *) - sizeof (int);
inp->cmd |= (tmp & IOCPARM_MASK) << 16;
if (iap->vi.in_size > VC_MAXMSGSIZE ||
iap->vi.out_size > VC_MAXMSGSIZE) {
CODA_FREE(inp, coda_ioctl_size);
return (EINVAL);
}
inp->rwflag = flag;
inp->len = iap->vi.in_size;
inp->data = (char *)(sizeof (struct coda_ioctl_in));
error = copyin(iap->vi.in, (char*)inp + (long)inp->data,
iap->vi.in_size);
if (error) {
CODA_FREE(inp, coda_ioctl_size);
return (error);
}
Osize = VC_MAXMSGSIZE;
error = coda_call(mdp, Isize + iap->vi.in_size, &Osize, (char *)inp);
/*
* Copy out the out buffer.
*/
if (!error) {
if (outp->len > iap->vi.out_size)
error = EINVAL;
else
error = copyout((char *)outp + (long)outp->data,
iap->vi.out, iap->vi.out_size);
}
CODA_FREE(inp, coda_ioctl_size);
return (error);
}
int
venus_getattr(void *mdp, struct CodaFid *fid, struct ucred *cred,
struct vattr *vap)
{
struct proc *p;
DECL(coda_getattr); /* sets Isize & Osize */
ALLOC(coda_getattr); /* sets inp & outp */
/*
* Send the open to venus.
*/
p = curthread->td_proc;
INIT_IN(&inp->ih, CODA_GETATTR, cred, p);
inp->Fid = *fid;
error = coda_call(mdp, Isize, &Osize, (char *)inp);
if (!error)
CNV_VV2V_ATTR(vap, &outp->attr);
CODA_FREE(inp, coda_getattr_size);
return (error);
}
int
venus_setattr(void *mdp, struct CodaFid *fid, struct vattr *vap,
struct ucred *cred)
{
struct proc *p;
DECL_NO_OUT(coda_setattr); /* sets Isize & Osize */
ALLOC_NO_OUT(coda_setattr); /* sets inp & outp */
/*
* Send the open to venus.
*/
p = curthread->td_proc;
INIT_IN(&inp->ih, CODA_SETATTR, cred, p);
inp->Fid = *fid;
CNV_V2VV_ATTR(&inp->attr, vap);
error = coda_call(mdp, Isize, &Osize, (char *)inp);
CODA_FREE(inp, coda_setattr_size);
return (error);
}
int
venus_access(void *mdp, struct CodaFid *fid, accmode_t accmode,
struct ucred *cred, struct proc *p)
{
DECL_NO_OUT(coda_access); /* sets Isize & Osize */
ALLOC_NO_OUT(coda_access); /* sets inp & outp */
/*
* Send the open to venus.
*/
INIT_IN(&inp->ih, CODA_ACCESS, cred, p);
inp->Fid = *fid;
/*
* NOTE: FreeBSD and Venus internals use the "data" in the low 3
* bits. Hence, the conversion.
*
* XXX: We cast accmode_t variable into an int.
*/
inp->flags = (int)accmode>>6;
error = coda_call(mdp, Isize, &Osize, (char *)inp);
CODA_FREE(inp, coda_access_size);
return (error);
}
int
venus_readlink(void *mdp, struct CodaFid *fid, struct ucred *cred,
struct proc *p, /*out*/ char **str, int *len)
{
DECL(coda_readlink); /* sets Isize & Osize */
coda_readlink_size += CODA_MAXPATHLEN;
ALLOC(coda_readlink); /* sets inp & outp */
/*
* Send the open to venus.
*/
INIT_IN(&inp->ih, CODA_READLINK, cred, p);
inp->Fid = *fid;
Osize += CODA_MAXPATHLEN;
error = coda_call(mdp, Isize, &Osize, (char *)inp);
if (!error) {
CODA_ALLOC(*str, char *, outp->count);
*len = outp->count;
bcopy((char *)outp + (long)outp->data, *str, *len);
}
CODA_FREE(inp, coda_readlink_size);
return (error);
}
int
venus_fsync(void *mdp, struct CodaFid *fid, struct proc *p)
{
DECL_NO_OUT(coda_fsync); /* sets Isize & Osize */
ALLOC_NO_OUT(coda_fsync); /* sets inp & outp */
/*
* Send the open to venus.
*
* XXX: should be cached mount cred.
*/
INIT_IN(&inp->ih, CODA_FSYNC, NOCRED, p);
inp->Fid = *fid;
error = coda_call(mdp, Isize, &Osize, (char *)inp);
CODA_FREE(inp, coda_fsync_size);
return (error);
}
int
venus_lookup(void *mdp, struct CodaFid *fid, const char *nm, int len,
struct ucred *cred, struct proc *p, /*out*/ struct CodaFid *VFid,
int *vtype)
{
DECL(coda_lookup); /* sets Isize & Osize */
coda_lookup_size += len + 1;
ALLOC(coda_lookup); /* sets inp & outp */
/*
* Send the open to venus.
*/
INIT_IN(&inp->ih, CODA_LOOKUP, cred, p);
inp->Fid = *fid;
/*
* NOTE: Between version 1 and version 2 we have added an extra flag
* field to this structure. But because the string was at the end
* and because of the wierd way we represent strings by having the
* slot point to where the string characters are in the "heap", we
* can just slip the flag parameter in after the string slot pointer
* and veni that don't know better won't see this new flag field ...
* Otherwise we'd need two different venus_lookup functions.
*/
inp->name = Isize;
inp->flags = CLU_CASE_SENSITIVE; /* doesn't really matter for BSD */
STRCPY(name, nm, len); /* increments Isize */
error = coda_call(mdp, Isize, &Osize, (char *)inp);
if (!error) {
*VFid = outp->Fid;
*vtype = outp->vtype;
}
CODA_FREE(inp, coda_lookup_size);
return (error);
}
int
venus_create(void *mdp, struct CodaFid *fid, const char *nm, int len,
int exclusive, int mode, struct vattr *va, struct ucred *cred,
struct proc *p, /*out*/ struct CodaFid *VFid, struct vattr *attr)
{
DECL(coda_create); /* sets Isize & Osize */
coda_create_size += len + 1;
ALLOC(coda_create); /* sets inp & outp */
/*
* Send the open to venus.
*/
INIT_IN(&inp->ih, CODA_CREATE, cred, p);
inp->Fid = *fid;
inp->excl = exclusive ? C_O_EXCL : 0;
inp->mode = mode;
CNV_V2VV_ATTR(&inp->attr, va);
inp->name = Isize;
STRCPY(name, nm, len); /* increments Isize */
error = coda_call(mdp, Isize, &Osize, (char *)inp);
if (!error) {
*VFid = outp->Fid;
CNV_VV2V_ATTR(attr, &outp->attr);
}
CODA_FREE(inp, coda_create_size);
return (error);
}
int
venus_remove(void *mdp, struct CodaFid *fid, const char *nm, int len,
struct ucred *cred, struct proc *p)
{
DECL_NO_OUT(coda_remove); /* sets Isize & Osize */
coda_remove_size += len + 1;
ALLOC_NO_OUT(coda_remove); /* sets inp & outp */
/*
* Send the open to venus.
*/
INIT_IN(&inp->ih, CODA_REMOVE, cred, p);
inp->Fid = *fid;
inp->name = Isize;
STRCPY(name, nm, len); /* increments Isize */
error = coda_call(mdp, Isize, &Osize, (char *)inp);
CODA_FREE(inp, coda_remove_size);
return (error);
}
int
venus_link(void *mdp, struct CodaFid *fid, struct CodaFid *tfid,
const char *nm, int len, struct ucred *cred, struct proc *p)
{
DECL_NO_OUT(coda_link); /* sets Isize & Osize */
coda_link_size += len + 1;
ALLOC_NO_OUT(coda_link); /* sets inp & outp */
/*
* Send the open to venus.
*/
INIT_IN(&inp->ih, CODA_LINK, cred, p);
inp->sourceFid = *fid;
inp->destFid = *tfid;
inp->tname = Isize;
STRCPY(tname, nm, len); /* increments Isize */
error = coda_call(mdp, Isize, &Osize, (char *)inp);
CODA_FREE(inp, coda_link_size);
return (error);
}
int
venus_rename(void *mdp, struct CodaFid *fid, struct CodaFid *tfid,
const char *nm, int len, const char *tnm, int tlen, struct ucred *cred,
struct proc *p)
{
DECL_NO_OUT(coda_rename); /* sets Isize & Osize */
coda_rename_size += len + 1 + tlen + 1;
ALLOC_NO_OUT(coda_rename); /* sets inp & outp */
/*
* Send the open to venus.
*/
INIT_IN(&inp->ih, CODA_RENAME, cred, p);
inp->sourceFid = *fid;
inp->destFid = *tfid;
inp->srcname = Isize;
STRCPY(srcname, nm, len); /* increments Isize */
inp->destname = Isize;
STRCPY(destname, tnm, tlen); /* increments Isize */
error = coda_call(mdp, Isize, &Osize, (char *)inp);
CODA_FREE(inp, coda_rename_size);
return (error);
}
int
venus_mkdir(void *mdp, struct CodaFid *fid, const char *nm, int len,
struct vattr *va, struct ucred *cred, struct proc *p,
/*out*/ struct CodaFid *VFid, struct vattr *ova)
{
DECL(coda_mkdir); /* sets Isize & Osize */
coda_mkdir_size += len + 1;
ALLOC(coda_mkdir); /* sets inp & outp */
/*
* Send the open to venus.
*/
INIT_IN(&inp->ih, CODA_MKDIR, cred, p);
inp->Fid = *fid;
CNV_V2VV_ATTR(&inp->attr, va);
inp->name = Isize;
STRCPY(name, nm, len); /* increments Isize */
error = coda_call(mdp, Isize, &Osize, (char *)inp);
if (!error) {
*VFid = outp->Fid;
CNV_VV2V_ATTR(ova, &outp->attr);
}
CODA_FREE(inp, coda_mkdir_size);
return (error);
}
int
venus_rmdir(void *mdp, struct CodaFid *fid, const char *nm, int len,
struct ucred *cred, struct proc *p)
{
DECL_NO_OUT(coda_rmdir); /* sets Isize & Osize */
coda_rmdir_size += len + 1;
ALLOC_NO_OUT(coda_rmdir); /* sets inp & outp */
/*
* Send the open to venus.
*/
INIT_IN(&inp->ih, CODA_RMDIR, cred, p);
inp->Fid = *fid;
inp->name = Isize;
STRCPY(name, nm, len); /* increments Isize */
error = coda_call(mdp, Isize, &Osize, (char *)inp);
CODA_FREE(inp, coda_rmdir_size);
return (error);
}
int
venus_symlink(void *mdp, struct CodaFid *fid, const char *lnm, int llen,
const char *nm, int len, struct vattr *va, struct ucred *cred,
struct proc *p)
{
DECL_NO_OUT(coda_symlink); /* sets Isize & Osize */
coda_symlink_size += llen + 1 + len + 1;
ALLOC_NO_OUT(coda_symlink); /* sets inp & outp */
/*
* Send the open to venus.
*/
INIT_IN(&inp->ih, CODA_SYMLINK, cred, p);
inp->Fid = *fid;
CNV_V2VV_ATTR(&inp->attr, va);
inp->srcname = Isize;
STRCPY(srcname, lnm, llen); /* increments Isize */
inp->tname = Isize;
STRCPY(tname, nm, len); /* increments Isize */
error = coda_call(mdp, Isize, &Osize, (char *)inp);
CODA_FREE(inp, coda_symlink_size);
return (error);
}
/*
* XXX: Unused.
*/
int
venus_readdir(void *mdp, struct CodaFid *fid, int count, int offset,
struct ucred *cred, struct proc *p, /*out*/ char *buffer, int *len)
{
DECL(coda_readdir); /* sets Isize & Osize */
coda_readdir_size = VC_MAXMSGSIZE;
ALLOC(coda_readdir); /* sets inp & outp */
/*
* Send the open to venus.
*/
INIT_IN(&inp->ih, CODA_READDIR, cred, p);
inp->Fid = *fid;
inp->count = count;
inp->offset = offset;
Osize = VC_MAXMSGSIZE;
error = coda_call(mdp, Isize, &Osize, (char *)inp);
if (!error) {
bcopy((char *)outp + (long)outp->data, buffer, outp->size);
*len = outp->size;
}
CODA_FREE(inp, coda_readdir_size);
return (error);
}
int
venus_fhtovp(void *mdp, struct CodaFid *fid, struct ucred *cred,
struct proc *p, /*out*/ struct CodaFid *VFid, int *vtype)
{
DECL(coda_vget); /* sets Isize & Osize */
ALLOC(coda_vget); /* sets inp & outp */
/*
* Send the open to Venus.
*/
INIT_IN(&inp->ih, CODA_VGET, cred, p);
inp->Fid = *fid;
error = coda_call(mdp, Isize, &Osize, (char *)inp);
if (!error) {
*VFid = outp->Fid;
*vtype = outp->vtype;
}
CODA_FREE(inp, coda_vget_size);
return (error);
}

View File

@ -1,83 +0,0 @@
/*-
*
* Coda: an Experimental Distributed File System
* Release 3.1
*
* Copyright (c) 1987-1998 Carnegie Mellon University
* All Rights Reserved
*
* Permission to use, copy, modify and distribute this software and its
* documentation is hereby granted, provided that both the copyright
* notice and this permission notice appear in all copies of the
* software, derivative works or modified versions, and any portions
* thereof, and that both notices appear in supporting documentation, and
* that credit is given to Carnegie Mellon University in all documents
* and publicity pertaining to direct or indirect use of this code or its
* derivatives.
*
* CODA IS AN EXPERIMENTAL SOFTWARE SYSTEM AND IS KNOWN TO HAVE BUGS,
* SOME OF WHICH MAY HAVE SERIOUS CONSEQUENCES. CARNEGIE MELLON ALLOWS
* FREE USE OF THIS SOFTWARE IN ITS "AS IS" CONDITION. CARNEGIE MELLON
* DISCLAIMS ANY LIABILITY OF ANY KIND FOR ANY DAMAGES WHATSOEVER
* RESULTING DIRECTLY OR INDIRECTLY FROM THE USE OF THIS SOFTWARE OR OF
* ANY DERIVATIVE WORK.
*
* Carnegie Mellon encourages users of this software to return any
* improvements or extensions that they make, and to grant Carnegie
* Mellon the rights to redistribute these changes without encumbrance.
*
* @(#) src/sys/coda/coda_venus.h,v 1.1.1.1 1998/08/29 21:14:52 rvb Exp $
* $FreeBSD$
*/
#ifndef _CODA_VENUS_H_
#define _CODA_VENUS_H_
int venus_root(void *mdp, struct ucred *cred, struct proc *p,
/*out*/ struct CodaFid *VFid);
int venus_open(void *mdp, struct CodaFid *fid, int flag,
struct ucred *cred, struct proc *p, /*out*/ struct vnode **vp);
int venus_close(void *mdp, struct CodaFid *fid, int flag,
struct ucred *cred, struct proc *p);
void venus_read(void);
void venus_write(void);
int venus_ioctl(void *mdp, struct CodaFid *fid, int com, int flag,
caddr_t data, struct ucred *cred, struct proc *p);
int venus_getattr(void *mdp, struct CodaFid *fid, struct ucred *cred,
struct vattr *vap);
int venus_setattr(void *mdp, struct CodaFid *fid, struct vattr *vap,
struct ucred *cred);
int venus_access(void *mdp, struct CodaFid *fid, int mode,
struct ucred *cred, struct proc *p);
int venus_readlink(void *mdp, struct CodaFid *fid, struct ucred *cred,
struct proc *p, /*out*/ char **str, int *len);
int venus_fsync(void *mdp, struct CodaFid *fid, struct proc *p);
int venus_lookup(void *mdp, struct CodaFid *fid, const char *nm, int len,
struct ucred *cred, struct proc *p, /*out*/ struct CodaFid *VFid,
int *vtype);
int venus_create(void *mdp, struct CodaFid *fid, const char *nm, int len,
int exclusive, int mode, struct vattr *va, struct ucred *cred,
struct proc *p, /*out*/ struct CodaFid *VFid,
struct vattr *attr);
int venus_remove(void *mdp, struct CodaFid *fid, const char *nm, int len,
struct ucred *cred, struct proc *p);
int venus_link(void *mdp, struct CodaFid *fid, struct CodaFid *tfid,
const char *nm, int len, struct ucred *cred, struct proc *p);
int venus_rename(void *mdp, struct CodaFid *fid, struct CodaFid *tfid,
const char *nm, int len, const char *tnm, int tlen,
struct ucred *cred, struct proc *p);
int venus_mkdir(void *mdp, struct CodaFid *fid, const char *nm, int len,
struct vattr *va, struct ucred *cred, struct proc *p,
/*out*/ struct CodaFid *VFid, struct vattr *ova);
int venus_rmdir(void *mdp, struct CodaFid *fid, const char *nm, int len,
struct ucred *cred, struct proc *p);
int venus_symlink(void *mdp, struct CodaFid *fid, const char *lnm,
int llen, const char *nm, int len, struct vattr *va,
struct ucred *cred, struct proc *p);
int venus_readdir(void *mdp, struct CodaFid *fid, int count, int offset,
struct ucred *cred, struct proc *p, /*out*/ char *buffer,
int *len);
int venus_fhtovp(void *mdp, struct CodaFid *fid, struct ucred *cred,
struct proc *p, /*out*/ struct CodaFid *VFid, int *vtype);
#endif /* !_CODA_VENUS_H_ */

View File

@ -1,446 +0,0 @@
/*-
* Coda: an Experimental Distributed File System
* Release 3.1
*
* Copyright (c) 1987-1998 Carnegie Mellon University
* All Rights Reserved
*
* Permission to use, copy, modify and distribute this software and its
* documentation is hereby granted, provided that both the copyright
* notice and this permission notice appear in all copies of the
* software, derivative works or modified versions, and any portions
* thereof, and that both notices appear in supporting documentation, and
* that credit is given to Carnegie Mellon University in all documents
* and publicity pertaining to direct or indirect use of this code or its
* derivatives.
*
* CODA IS AN EXPERIMENTAL SOFTWARE SYSTEM AND IS KNOWN TO HAVE BUGS,
* SOME OF WHICH MAY HAVE SERIOUS CONSEQUENCES. CARNEGIE MELLON ALLOWS
* FREE USE OF THIS SOFTWARE IN ITS "AS IS" CONDITION. CARNEGIE MELLON
* DISCLAIMS ANY LIABILITY OF ANY KIND FOR ANY DAMAGES WHATSOEVER
* RESULTING DIRECTLY OR INDIRECTLY FROM THE USE OF THIS SOFTWARE OR OF
* ANY DERIVATIVE WORK.
*
* Carnegie Mellon encourages users of this software to return any
* improvements or extensions that they make, and to grant Carnegie
* Mellon the rights to redistribute these changes without encumbrance.
*
* @(#) src/sys/cfs/coda_vfsops.c,v 1.1.1.1 1998/08/29 21:14:52 rvb Exp $
*/
/*-
* Mach Operating System
* Copyright (c) 1989 Carnegie-Mellon University
* All rights reserved. The CMU software License Agreement specifies
* the terms and conditions for use and redistribution.
*/
/*
* This code was written for the Coda filesystem at Carnegie Mellon
* University. Contributers include David Steere, James Kistler, and
* M. Satyanarayanan.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/conf.h>
#include <sys/fcntl.h>
#include <sys/kernel.h>
#include <sys/lock.h>
#include <sys/malloc.h>
#include <sys/mount.h>
#include <sys/namei.h>
#include <sys/proc.h>
#include <fs/coda/coda.h>
#include <fs/coda/cnode.h>
#include <fs/coda/coda_vfsops.h>
#include <fs/coda/coda_venus.h>
#include <fs/coda/coda_subr.h>
#include <fs/coda/coda_opstats.h>
MALLOC_DEFINE(M_CODA, "coda", "Various Coda Structures");
int codadebug = 0;
int coda_vfsop_print_entry = 0;
#define ENTRY do { \
if (coda_vfsop_print_entry) \
myprintf(("Entered %s\n", __func__)); \
} while (0)
struct vnode *coda_ctlvp;
/*
* Structure to keep statistics of internally generated/satisfied calls.
*/
static struct coda_op_stats coda_vfsopstats[CODA_VFSOPS_SIZE];
#define MARK_ENTRY(op) (coda_vfsopstats[op].entries++)
#define MARK_INT_SAT(op) (coda_vfsopstats[op].sat_intrn++)
#define MARK_INT_FAIL(op) (coda_vfsopstats[op].unsat_intrn++)
#define MARK_INT_GEN(op) (coda_vfsopstats[op].gen_intrn++)
int
coda_vfsopstats_init(void)
{
int i;
for (i=0; i<CODA_VFSOPS_SIZE;i++) {
coda_vfsopstats[i].opcode = i;
coda_vfsopstats[i].entries = 0;
coda_vfsopstats[i].sat_intrn = 0;
coda_vfsopstats[i].unsat_intrn = 0;
coda_vfsopstats[i].gen_intrn = 0;
}
return (0);
}
static const char *coda_opts[] = { "from", NULL };
/*
* cfs mount vfsop
*
* Set up mount info record and attach it to vfs struct.
*/
/*ARGSUSED*/
int
coda_mount(struct mount *vfsp)
{
struct vnode *dvp;
struct cnode *cp;
struct cdev *dev;
struct coda_mntinfo *mi;
struct vnode *rootvp;
struct CodaFid rootfid = INVAL_FID;
struct CodaFid ctlfid = CTL_FID;
int error;
struct nameidata ndp;
ENTRY;
char *from;
if (vfs_filteropt(vfsp->mnt_optnew, coda_opts))
return (EINVAL);
from = vfs_getopts(vfsp->mnt_optnew, "from", &error);
if (error)
return (error);
coda_vfsopstats_init();
coda_vnodeopstats_init();
MARK_ENTRY(CODA_MOUNT_STATS);
if (CODA_MOUNTED(vfsp)) {
MARK_INT_FAIL(CODA_MOUNT_STATS);
return (EBUSY);
}
/*
* Validate mount device. Similar to getmdev().
*/
NDINIT(&ndp, LOOKUP, FOLLOW, UIO_SYSSPACE, from, curthread);
error = namei(&ndp);
dvp = ndp.ni_vp;
if (error) {
MARK_INT_FAIL(CODA_MOUNT_STATS);
return (error);
}
if (dvp->v_type != VCHR) {
MARK_INT_FAIL(CODA_MOUNT_STATS);
vrele(dvp);
NDFREE(&ndp, NDF_ONLY_PNBUF);
return (ENXIO);
}
dev = dvp->v_rdev;
vrele(dvp);
NDFREE(&ndp, NDF_ONLY_PNBUF);
/*
* Initialize the mount record and link it to the vfs struct.
*/
mi = dev2coda_mntinfo(dev);
if (!mi) {
MARK_INT_FAIL(CODA_MOUNT_STATS);
printf("Coda mount: %s is not a cfs device\n", from);
return (ENXIO);
}
if (!VC_OPEN(&mi->mi_vcomm)) {
MARK_INT_FAIL(CODA_MOUNT_STATS);
return (ENODEV);
}
/*
* No initialization (here) of mi_vcomm!
*/
vfsp->mnt_data = mi;
vfs_getnewfsid (vfsp);
mi->mi_vfsp = vfsp;
mi->mi_started = 0; /* XXX See coda_root() */
/*
* Make a root vnode to placate the Vnode interface, but don't
* actually make the CODA_ROOT call to venus until the first call to
* coda_root in case a server is down while venus is starting.
*/
cp = make_coda_node(&rootfid, vfsp, VDIR);
rootvp = CTOV(cp);
rootvp->v_vflag |= VV_ROOT;
cp = make_coda_node(&ctlfid, vfsp, VREG);
coda_ctlvp = CTOV(cp);
/*
* Add vfs and rootvp to chain of vfs hanging off mntinfo.
*/
mi->mi_vfsp = vfsp;
mi->mi_rootvp = rootvp;
vfs_mountedfrom(vfsp, from);
/*
* Error is currently guaranteed to be zero, but in case some code
* changes...
*/
CODADEBUG(1, myprintf(("coda_mount returned %d\n", error)););
if (error)
MARK_INT_FAIL(CODA_MOUNT_STATS);
else
MARK_INT_SAT(CODA_MOUNT_STATS);
return (error);
}
int
coda_unmount(struct mount *vfsp, int mntflags)
{
struct coda_mntinfo *mi = vftomi(vfsp);
int active, error = 0;
ENTRY;
MARK_ENTRY(CODA_UMOUNT_STATS);
if (!CODA_MOUNTED(vfsp)) {
MARK_INT_FAIL(CODA_UMOUNT_STATS);
return (EINVAL);
}
if (mi->mi_vfsp == vfsp) {
/*
* We found the victim.
*/
if (!IS_UNMOUNTING(VTOC(mi->mi_rootvp)))
return (EBUSY); /* Venus is still running */
#ifdef DEBUG
printf("coda_unmount: ROOT: vp %p, cp %p\n", mi->mi_rootvp,
VTOC(mi->mi_rootvp));
#endif
vrele(mi->mi_rootvp);
mi->mi_rootvp = NULL;
vrele(coda_ctlvp);
coda_ctlvp = NULL;
active = coda_kill(vfsp, NOT_DOWNCALL);
error = vflush(mi->mi_vfsp, 0, FORCECLOSE, curthread);
#ifdef CODA_VERBOSE
printf("coda_unmount: active = %d, vflush active %d\n",
active, error);
#endif
error = 0;
/*
* I'm going to take this out to allow lookups to go through.
* I'm not sure it's important anyway. -- DCS 2/2/94
*/
/* vfsp->VFS_DATA = NULL; */
/*
* No more vfsp's to hold onto.
*/
mi->mi_vfsp = NULL;
if (error)
MARK_INT_FAIL(CODA_UMOUNT_STATS);
else
MARK_INT_SAT(CODA_UMOUNT_STATS);
return (error);
}
return (EINVAL);
}
/*
* Find root of cfs.
*/
int
coda_root(struct mount *vfsp, int flags, struct vnode **vpp)
{
struct coda_mntinfo *mi = vftomi(vfsp);
int error;
struct proc *p;
struct thread *td;
struct CodaFid VFid;
static const struct CodaFid invalfid = INVAL_FID;
td = curthread;
p = td->td_proc;
ENTRY;
MARK_ENTRY(CODA_ROOT_STATS);
if (vfsp == mi->mi_vfsp) {
/*
* Cache the root across calls. We only need to pass the
* request on to Venus if the root vnode is the dummy we
* installed in coda_mount() with all c_fid members zeroed.
*
* XXX In addition, we assume that the first call to
* coda_root() is from vfs_mount() (before the call to
* checkdirs()) and return the dummy root node to avoid a
* deadlock. This bug is fixed in the Coda CVS repository
* but not in any released versions as of 6 Mar 2003.
*/
if (memcmp(&VTOC(mi->mi_rootvp)->c_fid, &invalfid,
sizeof(struct CodaFid)) != 0 || mi->mi_started == 0) {
/*
* Found valid root.
*/
*vpp = mi->mi_rootvp;
mi->mi_started = 1;
/*
* On Mach, this is vref. On FreeBSD, vref +
* vn_lock.
*/
vref(*vpp);
vn_lock(*vpp, LK_EXCLUSIVE | LK_RETRY);
MARK_INT_SAT(CODA_ROOT_STATS);
return (0);
}
}
error = venus_root(vftomi(vfsp), td->td_ucred, p, &VFid);
if (!error) {
/*
* Save the new rootfid in the cnode, and rehash the cnode
* into the cnode hash with the new fid key.
*/
coda_unsave(VTOC(mi->mi_rootvp));
VTOC(mi->mi_rootvp)->c_fid = VFid;
coda_save(VTOC(mi->mi_rootvp));
*vpp = mi->mi_rootvp;
vref(*vpp);
vn_lock(*vpp, LK_EXCLUSIVE | LK_RETRY);
MARK_INT_SAT(CODA_ROOT_STATS);
} else if (error == ENODEV || error == EINTR) {
/*
* Gross hack here!
*
* If Venus fails to respond to the CODA_ROOT call, coda_call
* returns ENODEV. Return the uninitialized root vnode to
* allow vfs operations such as unmount to continue. Without
* this hack, there is no way to do an unmount if Venus dies
* before a successful CODA_ROOT call is done. All vnode
* operations will fail.
*/
*vpp = mi->mi_rootvp;
vref(*vpp);
vn_lock(*vpp, LK_EXCLUSIVE | LK_RETRY);
MARK_INT_FAIL(CODA_ROOT_STATS);
error = 0;
} else {
CODADEBUG(CODA_ROOT, myprintf(("error %d in CODA_ROOT\n",
error)););
MARK_INT_FAIL(CODA_ROOT_STATS);
}
return (error);
}
/*
* Get filesystem statistics.
*/
int
coda_statfs(struct mount *vfsp, struct statfs *sbp)
{
ENTRY;
MARK_ENTRY(CODA_STATFS_STATS);
if (!CODA_MOUNTED(vfsp)) {
MARK_INT_FAIL(CODA_STATFS_STATS);
return (EINVAL);
}
/*
* XXX - what to do about f_flags, others? --bnoble
*
* We just make up free space counts that are sufficiently large.
*/
sbp->f_flags = 0;
sbp->f_bsize = 8192; /* XXX */
sbp->f_iosize = 8192; /* XXX */
#define CODA_SFS_SIZ 0x8AB75D
sbp->f_blocks = CODA_SFS_SIZ;
sbp->f_bfree = CODA_SFS_SIZ;
sbp->f_bavail = CODA_SFS_SIZ;
sbp->f_files = CODA_SFS_SIZ;
sbp->f_ffree = CODA_SFS_SIZ;
MARK_INT_SAT(CODA_STATFS_STATS);
return (0);
}
/*
* Flush any pending I/O.
*/
int
coda_sync(struct mount *vfsp, int waitfor)
{
ENTRY;
MARK_ENTRY(CODA_SYNC_STATS);
MARK_INT_SAT(CODA_SYNC_STATS);
return (0);
}
/*
* fhtovp is now what vget used to be in 4.3-derived systems. For some silly
* reason, vget is now keyed by a 32 bit ino_t, rather than a type-specific
* fid.
*
* XXX: coda_fhtovp is currently not hooked up, so no NFS export for Coda.
* We leave it here in the hopes that someone will find it someday and hook
* it up. Among other things, it will need some reworking to match the
* vfs_fhtovp_t prototype.
*/
int
coda_fhtovp(struct mount *vfsp, struct fid *fhp, struct mbuf *nam,
struct vnode **vpp, int *exflagsp, struct ucred **creadanonp)
{
struct cfid *cfid = (struct cfid *)fhp;
struct cnode *cp = NULL;
int error;
struct thread *td = curthread; /* XXX -mach */
struct proc *p = td->td_proc;
struct CodaFid VFid;
int vtype;
ENTRY;
MARK_ENTRY(CODA_VGET_STATS);
/*
* Check for vget of control object.
*/
if (IS_CTL_FID(&cfid->cfid_fid)) {
*vpp = coda_ctlvp;
vref(coda_ctlvp);
MARK_INT_SAT(CODA_VGET_STATS);
return (0);
}
error = venus_fhtovp(vftomi(vfsp), &cfid->cfid_fid, td->td_ucred, p,
&VFid, &vtype);
if (error) {
CODADEBUG(CODA_VGET, myprintf(("vget error %d\n",error)););
*vpp = NULL;
} else {
CODADEBUG(CODA_VGET, myprintf(("vget: %s type %d result "
"%d\n", coda_f2s(&VFid), vtype, error)););
cp = make_coda_node(&VFid, vfsp, vtype);
*vpp = CTOV(cp);
}
return (error);
}
struct vfsops coda_vfsops = {
.vfs_mount = coda_mount,
.vfs_root = coda_root,
.vfs_statfs = coda_statfs,
.vfs_sync = coda_sync,
.vfs_unmount = coda_unmount,
};
VFS_SET(coda_vfsops, coda, VFCF_NETWORK);

View File

@ -1,60 +0,0 @@
/*-
*
* Coda: an Experimental Distributed File System
* Release 3.1
*
* Copyright (c) 1987-1998 Carnegie Mellon University
* All Rights Reserved
*
* Permission to use, copy, modify and distribute this software and its
* documentation is hereby granted, provided that both the copyright
* notice and this permission notice appear in all copies of the
* software, derivative works or modified versions, and any portions
* thereof, and that both notices appear in supporting documentation, and
* that credit is given to Carnegie Mellon University in all documents
* and publicity pertaining to direct or indirect use of this code or its
* derivatives.
*
* CODA IS AN EXPERIMENTAL SOFTWARE SYSTEM AND IS KNOWN TO HAVE BUGS,
* SOME OF WHICH MAY HAVE SERIOUS CONSEQUENCES. CARNEGIE MELLON ALLOWS
* FREE USE OF THIS SOFTWARE IN ITS "AS IS" CONDITION. CARNEGIE MELLON
* DISCLAIMS ANY LIABILITY OF ANY KIND FOR ANY DAMAGES WHATSOEVER
* RESULTING DIRECTLY OR INDIRECTLY FROM THE USE OF THIS SOFTWARE OR OF
* ANY DERIVATIVE WORK.
*
* Carnegie Mellon encourages users of this software to return any
* improvements or extensions that they make, and to grant Carnegie
* Mellon the rights to redistribute these changes without encumbrance.
*
* @(#) src/sys/cfs/coda_vfsops.h,v 1.1.1.1 1998/08/29 21:14:52 rvb Exp $
* $FreeBSD$
*/
#ifndef _CODA_VFSOPS_H_
#define _CODA_VFSOPS_H_
/*
* cfid structure:
*
* This overlays the fid structure (see vfs.h); only used below and will
* probably go away.
*/
struct cfid {
u_short cfid_len;
u_short padding;
struct CodaFid cfid_fid;
};
struct mbuf;
struct mount;
int coda_vfsopstats_init(void);
int coda_fhtovp(struct mount *, struct fid *, struct mbuf *,
struct vnode **, int *, struct ucred **);
vfs_mount_t coda_mount;
vfs_unmount_t coda_unmount;
vfs_root_t coda_root;
vfs_statfs_t coda_statfs;
vfs_sync_t coda_sync;
#endif /* !_CODA_VFSOPS_H_ */

File diff suppressed because it is too large Load Diff

View File

@ -1,84 +0,0 @@
/*-
*
* Coda: an Experimental Distributed File System
* Release 3.1
*
* Copyright (c) 1987-1998 Carnegie Mellon University
* All Rights Reserved
*
* Permission to use, copy, modify and distribute this software and its
* documentation is hereby granted, provided that both the copyright
* notice and this permission notice appear in all copies of the
* software, derivative works or modified versions, and any portions
* thereof, and that both notices appear in supporting documentation, and
* that credit is given to Carnegie Mellon University in all documents
* and publicity pertaining to direct or indirect use of this code or its
* derivatives.
*
* CODA IS AN EXPERIMENTAL SOFTWARE SYSTEM AND IS KNOWN TO HAVE BUGS,
* SOME OF WHICH MAY HAVE SERIOUS CONSEQUENCES. CARNEGIE MELLON ALLOWS
* FREE USE OF THIS SOFTWARE IN ITS "AS IS" CONDITION. CARNEGIE MELLON
* DISCLAIMS ANY LIABILITY OF ANY KIND FOR ANY DAMAGES WHATSOEVER
* RESULTING DIRECTLY OR INDIRECTLY FROM THE USE OF THIS SOFTWARE OR OF
* ANY DERIVATIVE WORK.
*
* Carnegie Mellon encourages users of this software to return any
* improvements or extensions that they make, and to grant Carnegie
* Mellon the rights to redistribute these changes without encumbrance.
*
* @(#) src/sys/coda/coda_vnops.h,v 1.1.1.1 1998/08/29 21:14:52 rvb Exp $
* $FreeBSD$
*/
/*
* Mach Operating System
* Copyright (c) 1990 Carnegie-Mellon University
* Copyright (c) 1989 Carnegie-Mellon University
* All rights reserved. The CMU software License Agreement specifies
* the terms and conditions for use and redistribution.
*/
/*
* This code was written for the Coda filesystem at Carnegie Mellon
* University. Contributers include David Steere, James Kistler, and
* M. Satyanarayanan.
*/
#ifndef _CODA_VNOPS_H_
#define _CODA_VNOPS_H_
/*
* FreeBSD interfaces to the vnodeops.
*/
vop_open_t coda_open;
vop_close_t coda_close;
vop_read_t coda_read;
vop_write_t coda_write;
vop_ioctl_t coda_ioctl;
vop_getattr_t coda_getattr;
vop_setattr_t coda_setattr;
vop_access_t coda_access;
vop_readlink_t coda_readlink;
vop_fsync_t coda_fsync;
vop_inactive_t coda_inactive;
vop_cachedlookup_t coda_lookup;
vop_create_t coda_create;
vop_remove_t coda_remove;
vop_link_t coda_link;
vop_rename_t coda_rename;
vop_mkdir_t coda_mkdir;
vop_rmdir_t coda_rmdir;
vop_symlink_t coda_symlink;
vop_readdir_t coda_readdir;
vop_strategy_t coda_strategy;
vop_reclaim_t coda_reclaim;
vop_lock1_t coda_lock;
vop_unlock_t coda_unlock;
vop_islocked_t coda_islocked;
vop_pathconf_t coda_pathconf;
int coda_rdwr(struct vnode *vp, struct uio *uiop, enum uio_rw rw,
int ioflag, struct ucred *cred, struct thread *td);
void coda_print_cred(struct ucred *cred);
#endif /* !_CODA_VNOPS_H_ */

View File

@ -1,387 +0,0 @@
/*-
* Copyright (c) 1998, 1999 Semen Ustimenko (semenu@FreeBSD.org)
* 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.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
*
* $FreeBSD$
*/
/*#define HPFS_DEBUG 10*/
typedef u_int32_t lsn_t; /* Logical Sector Number */
typedef struct {
lsn_t lsn1;
lsn_t lsn2;
} rsp_t; /* Redundant Sector Pointer */
typedef struct {
u_int32_t cnt;
lsn_t lsn;
} sptr_t; /* Storage Pointer */
#define SUBLOCK 0x10
#define SUSIZE DEV_BSIZE
#define SPBLOCK 0x11
#define SPSIZE DEV_BSIZE
#define BMSIZE (4 * DEV_BSIZE)
#define HPFS_MAXFILENAME 255
#define SU_MAGIC ((u_int64_t)0xFA53E9C5F995E849)
struct sublock {
u_int64_t su_magic;
u_int8_t su_hpfsver;
u_int8_t su_fnctver;
u_int16_t unused;
lsn_t su_rootfno; /* Root Fnode */
u_int32_t su_btotal; /* Total blocks */
u_int32_t su_badbtotal; /* Bad Sectors total */
rsp_t su_bitmap;
rsp_t su_badbl;
u_long su_chkdskdate;
u_long su_dskoptdate;
u_int32_t su_dbbsz; /* Sectors in DirBlock Band */
lsn_t su_dbbstart;
lsn_t su_dbbend;
lsn_t su_dbbbitmap;
char su_volname[0x20];
lsn_t su_uidt; /* Ptr to User ID Table (8 sect) */
};
#define SP_MAGIC ((u_int64_t)0xFA5229C5F9911849)
#define SP_DIRTY 0x0001
#define SP_SPDBINUSE 0x0002
#define SP_HFINUSE 0x0004
#define SP_BADSECT 0x0008
#define SP_BADBMBL 0x0010
#define SP_FASTFRMT 0x0020
#define SP_OLDHPFS 0x0080
#define SP_IDASD 0x0100
#define SP_RDASD 0x0200
#define SP_DASD 0x0400
#define SP_MMACTIVE 0x0800
#define SP_DCEACLS 0x1000
#define SP_DSADDIRTY 0x2000
struct spblock {
u_int64_t sp_magic;
u_int16_t sp_flag;
u_int8_t sp_mmcontf;
u_int8_t unused;
lsn_t sp_hf; /* HotFix list */
u_int32_t sp_hfinuse; /* HotFixes in use */
u_int32_t sp_hfavail; /* HotFixes available */
u_int32_t sp_spdbavail; /* Spare DirBlocks available */
u_int32_t sp_spdbmax; /* Spare DirBlocks maximum */
lsn_t sp_cpi;
u_int32_t sp_cpinum;
u_int32_t sp_suchecksum;
u_int32_t sp_spchecksum;
u_int8_t reserved[0x3C];
lsn_t sp_spdb[0x65];
};
#define DE_SPECIAL 0x0001
#define DE_ACL 0x0002
#define DE_DOWN 0x0004
#define DE_END 0x0008
#define DE_EALIST 0x0010
#define DE_EPERM 0x0020
#define DE_EXPLACL 0x0040
#define DE_NEEDEA 0x0080
#define DE_RONLY 0x0100
#define DE_HIDDEN 0x0200
#define DE_SYSTEM 0x0400
#define DE_VOLLABEL 0x0800
#define DE_DIR 0x1000
#define DE_ARCHIV 0x2000
#define DE_DOWNLSN(dep) (*(lsn_t *)((caddr_t)(dep) + (dep)->de_reclen - sizeof(lsn_t)))
#define DE_NEXTDE(dep) ((struct hpfsdirent *)((caddr_t)(dep) + (dep)->de_reclen))
typedef struct hpfsdirent {
u_int16_t de_reclen;
u_int16_t de_flag;
lsn_t de_fnode;
u_long de_mtime;
u_int32_t de_size;
u_long de_atime;
u_long de_ctime;
u_int32_t de_ealen;
u_int8_t de_flexflag;
u_int8_t de_cpid;
u_int8_t de_namelen;
char de_name[1];
/* ... de_flex; */
/* lsn_t de_down; */
} hpfsdirent_t;
#define D_BSIZE (DEV_BSIZE*4)
#define D_MAGIC 0x77E40AAE
#define D_DIRENT(dbp) ((hpfsdirent_t *)((caddr_t)dbp + sizeof(dirblk_t)))
#define D_DE(dbp, deoff) ((hpfsdirent_t *)((caddr_t)dbp + sizeof(dirblk_t) + (deoff)))
typedef struct dirblk {
u_int32_t d_magic;
u_int32_t d_freeoff; /* Offset of first free byte */
u_int32_t d_chcnt; /* Change count */
lsn_t d_parent;
lsn_t d_self;
} dirblk_t;
/*
* Allocation Block (ALBLK)
*/
#define AB_HBOFFEO 0x01
#define AB_FNPARENT 0x20
#define AB_SUGGBSCH 0x40
#define AB_NODES 0x80
#define AB_ALLEAF(abp) ((alleaf_t *)((caddr_t)(abp) + sizeof(alblk_t)))
#define AB_ALNODE(abp) ((alnode_t *)((caddr_t)(abp) + sizeof(alblk_t)))
#define AB_FREEALP(abp) ((alleaf_t *)((caddr_t)(abp) + (abp)->ab_freeoff))
#define AB_FREEANP(abp) ((alnode_t *)((caddr_t)(abp) + (abp)->ab_freeoff))
#define AB_LASTALP(abp) (AB_ALLEAF(abp) + (abp)->ab_busycnt - 1)
#define AB_LASTANP(abp) (AB_ALNODE(abp) + (abp)->ab_busycnt - 1)
#define AB_ADDNREC(abp, sz, n) { \
(abp)->ab_busycnt += (n); \
(abp)->ab_freecnt -= (n); \
(abp)->ab_freeoff += (n) * (sz); \
}
#define AB_RMNREC(abp, sz, n) { \
(abp)->ab_busycnt -= (n); \
(abp)->ab_freecnt += (n); \
(abp)->ab_freeoff -= (n) * (sz);\
}
#define AB_ADDAL(abp) AB_ADDNREC(abp,sizeof(alleaf_t), 1)
#define AB_ADDAN(abp) AB_ADDNREC(abp,sizeof(alnode_t), 1)
#define AB_RMAL(abp) AB_RMNREC(abp,sizeof(alleaf_t), 1)
#define AB_RMAN(abp) AB_RMNREC(abp,sizeof(alnode_t), 1)
typedef struct alblk {
u_int8_t ab_flag;
u_int8_t ab_res[3];
u_int8_t ab_freecnt;
u_int8_t ab_busycnt;
u_int16_t ab_freeoff;
} alblk_t;
/*
* FNode
*/
#define FNODESIZE DEV_BSIZE
#define FN_MAGIC 0xF7E40AAE
struct fnode {
u_int32_t fn_magic;
u_int64_t fn_readhist;
u_int8_t fn_namelen;
char fn_name[0xF]; /* First 15 symbols or less */
lsn_t fn_parent;
sptr_t fn_extacl;
u_int16_t fn_acllen;
u_int8_t fn_extaclflag;
u_int8_t fn_histbitcount;
sptr_t fn_extea;
u_int16_t fn_ealen; /* Len of EAs in Fnode */
u_int8_t fn_exteaflag; /* EAs in exteas */
u_int8_t fn_flag;
alblk_t fn_ab;
u_int8_t fn_abd[0x60];
u_int32_t fn_size;
u_int32_t fn_reqea;
u_int8_t fn_uid[0x10];
u_int16_t fn_intoff;
u_int8_t fn_1dasdthr;
u_int8_t fn_dasdthr;
u_int32_t fn_dasdlim;
u_int32_t fn_dasdusage;
u_int8_t fn_int[0x13c];
};
#define EA_NAME(eap) ((char *)(((caddr_t)(eap)) + sizeof(struct ea)))
struct ea {
u_int8_t ea_type; /* 0 - plain val */
/* 1 - sptr to val */
/* 3 - lsn point to AlSec, cont. val */
u_int8_t ea_namelen;
u_int16_t ea_vallen;
/*u_int8_t ea_name[]; */
/*u_int8_t ea_val[]; */
};
/*
* Allocation Block Data (ALNODE)
*
* NOTE: AlNodes are used when there are too many fragments
* to represent the data in the AlBlk
*/
#define AN_SET(anp,nextoff,lsn) { \
(anp)->an_nextoff = (nextoff); \
(anp)->an_lsn = (lsn); \
}
typedef struct alnode {
u_int32_t an_nextoff; /* next node offset in blocks */
lsn_t an_lsn; /* position of AlSec structure */
} alnode_t;
/*
* Allocaion Block Data (ALLEAF)
*
* NOTE: Leaves are used to point at contiguous block of data
* (a fragment or an "extent");
*/
#define AL_SET(alp,off,len,lsn) { \
(alp)->al_off = (off); \
(alp)->al_len = (len); \
(alp)->al_lsn = (lsn); \
}
typedef struct alleaf {
u_int32_t al_off; /* offset in blocks */
u_int32_t al_len; /* len in blocks */
lsn_t al_lsn; /* phys position */
} alleaf_t;
/*
* Allocation Sector
*
* NOTE: AlSecs are not initialized before use, so they ussually
* look full of junk. Use the AlBlk tto validate the data.
*/
#define AS_MAGIC 0x37E40AAE
typedef struct alsec {
u_int32_t as_magic;
lsn_t as_self;
lsn_t as_parent;
alblk_t as_ab;
u_int8_t as_abd[0x1E0];
} alsec_t;
/*
* Code Page structures
*/
struct cpdblk {
u_int16_t b_country; /* Country code */
u_int16_t b_cpid; /* CP ID */
u_int16_t b_dbcscnt; /* Count of DBCS ranges in CP */
char b_upcase[0x80]; /* Case conversion table */
u_int16_t b_dbcsrange; /* Start/End DBCS range pairs */
};
#define CPD_MAGIC ((u_int32_t)0x894521F7)
struct cpdsec {
u_int32_t d_magic;
u_int16_t d_cpcnt; /* CP Data count */
u_int16_t d_cpfirst; /* Index of first CP Data */
u_int32_t d_checksum[3]; /* CP Data checksumms */
u_int16_t d_offset[3]; /* Offsets of CP Data blocks */
struct cpdblk d_cpdblk[3]; /* Array of CP Data Blocks */
};
struct cpiblk {
u_int16_t b_country; /* Country code */
u_int16_t b_cpid; /* CP ID */
u_int32_t b_checksum;
lsn_t b_cpdsec; /* Pointer to CP Data Sector */
u_int16_t b_vcpid; /* Volume spec. CP ID */
u_int16_t b_dbcscnt; /* Count of DBCS ranges in CP */
};
#define CPI_MAGIC ((u_int32_t)0x494521F7)
struct cpisec {
u_int32_t s_magic;
u_int32_t s_cpicnt; /* Count of CPI's in this sector */
u_int32_t s_cpifirst; /* Index of first CPI in this sector */
lsn_t s_next; /* Pointer to next CPI Sector */
struct cpiblk s_cpi[0x1F]; /* Array of CPI blocks */
};
struct hpfsmount {
struct sublock hpm_su;
struct spblock hpm_sp;
struct mount * hpm_mp;
struct vnode * hpm_devvp; /* XXX: lose this, it's in hpfsmount */
struct g_consumer *hpm_cp;
struct bufobj *hpm_bo;
struct cdev *hpm_dev;
uid_t hpm_uid;
gid_t hpm_gid;
mode_t hpm_mode;
lsn_t * hpm_bmind;
struct cpdblk * hpm_cpdblk; /* Array of CP Data Blocks */
u_char hpm_u2d[0x80]; /* Unix to DOS Table*/
u_char hpm_d2u[0x80]; /* DOS to Unix Table*/
u_long hpm_bavail; /* Blocks available */
u_long hpm_dbnum; /* Data Band number */
u_int8_t * hpm_bitmap;
};
#define H_PARVALID 0x0002 /* parent info is valid */
#define H_CHANGE 0x0004 /* node date was changed */
#define H_PARCHANGE 0x0008 /* parent node date was changed */
#define H_INVAL 0x0010 /* Invalid node */
struct hpfsnode {
struct mtx h_interlock;
struct hpfsmount *h_hpmp;
struct fnode h_fn;
struct vnode * h_vp;
struct vnode * h_devvp; /* XXX: remove, hpfsmount has it */
struct cdev *h_dev;
lsn_t h_no;
uid_t h_uid;
gid_t h_gid;
mode_t h_mode;
u_int32_t h_flag;
/* parent dir information */
u_long h_mtime;
u_long h_atime;
u_long h_ctime;
char h_name[HPFS_MAXFILENAME+1]; /* Used to speedup dirent */
int h_namelen; /* lookup */
};
/* This overlays the fid structure (see <sys/mount.h>) */
struct hpfid {
u_int16_t hpfid_len; /* Length of structure. */
u_int16_t hpfid_pad; /* Force 32-bit alignment. */
lsn_t hpfid_ino; /* File number (ino). */
int32_t hpfid_gen; /* Generation number. */
};
#if defined(HPFS_DEBUG)
#define dprintf(a) printf a
#if HPFS_DEBUG > 1
#define ddprintf(a) printf a
#else
#define ddprintf(a)
#endif
#else
#define dprintf(a)
#define ddprintf(a)
#endif
#if __FreeBSD_version >= 300000
MALLOC_DECLARE(M_HPFSMNT);
MALLOC_DECLARE(M_HPFSNO);
#endif
#define VFSTOHPFS(mp) ((struct hpfsmount *)((mp)->mnt_data))
#define VTOHP(v) ((struct hpfsnode *)((v)->v_data))
#define HPTOV(h) ((struct vnode *)((h)->h_vp))
#define FID(f) (*((lsn_t *)(f)->fid_data))
extern struct vop_vector hpfs_vnodeops;

View File

@ -1,907 +0,0 @@
/*-
* Copyright (c) 1998, 1999 Semen Ustimenko (semenu@FreeBSD.org)
* 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.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
*
* $FreeBSD$
*/
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/proc.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/vnode.h>
#include <sys/mount.h>
#include <sys/namei.h>
#include <sys/malloc.h>
#include <sys/bio.h>
#include <sys/buf.h>
#include <fs/hpfs/hpfs.h>
#include <fs/hpfs/hpfs_subr.h>
#define AE_DONE 0 /* Nothing to change */
#define AE_SPLIT 2 /* Split was done, ranp is valid */
int hpfs_addextentr (struct hpfsmount *, lsn_t, alleaf_t *,
alnode_t *, u_long *);
int hpfs_allocalsec (struct hpfsmount *, lsn_t, struct buf **);
int hpfs_alblk2alsec (struct hpfsmount *, alblk_t *, alsec_t **,
struct buf **);
int hpfs_splitalsec (struct hpfsmount *, alsec_t *, alsec_t **,
struct buf **);
int hpfs_concatalsec (struct hpfsmount *, alsec_t *, alsec_t *,
alnode_t *);
/*
* Map file offset to disk offset. hpfsnode have to be locked.
*/
int
hpfs_hpbmap(hp, bn, bnp, runp)
struct hpfsnode *hp;
daddr_t bn;
daddr_t *bnp;
int *runp;
{
struct buf *bp;
alblk_t * abp;
alleaf_t *alp;
alnode_t *anp;
int error, i;
dprintf(("hpfs_hpbmap(0x%x, 0x%x): ",hp->h_no, bn));
bp = NULL;
abp = &hp->h_fn.fn_ab;
alp = (alleaf_t *)&hp->h_fn.fn_abd;
anp = (alnode_t *)&hp->h_fn.fn_abd;
dive:
if (abp->ab_flag & AB_NODES) {
for (i=0; i<abp->ab_busycnt; i++, anp++) {
dprintf(("[0x%x,0x%x] ",anp->an_nextoff,anp->an_lsn));
if (bn < anp->an_nextoff) {
alsec_t *asp;
dprintf(("< found | "));
if (bp)
brelse(bp);
error = bread(hp->h_devvp, anp->an_lsn,
DEV_BSIZE, NOCRED, &bp);
if (error) {
printf("hpfs_hpbmap: bread error\n");
brelse(bp);
return (error);
}
asp = (alsec_t *) bp->b_data;
if (asp->as_magic != AS_MAGIC) {
brelse(bp);
printf("hpfs_hpbmap: "
"MAGIC DOESN'T MATCH");
return (EINVAL);
}
abp = &asp->as_ab;
alp = (alleaf_t *)&asp->as_abd;
anp = (alnode_t *)&asp->as_abd;
goto dive;
}
}
} else {
for (i=0; i<abp->ab_busycnt; i++, alp++) {
dprintf(("[0x%x,0x%x,0x%x] ",
alp->al_off,alp->al_len,alp->al_lsn));
if ((bn >= alp->al_off) &&
(!alp->al_len || (bn < alp->al_off + alp->al_len))) {
dprintf(("found, "));
*bnp = bn - alp->al_off + alp->al_lsn;
dprintf((" 0x%x ", *bnp));
if (runp != NULL) {
if (alp->al_len)
*runp = alp->al_off - 1 +
alp->al_len - bn;
else
*runp = 3; /* XXX */
dprintf((" 0x%x cont", *runp));
}
if (bp)
brelse(bp);
dprintf(("\n"));
return (0);
}
}
}
dprintf(("END, notfound\n"));
if (bp)
brelse(bp);
dprintf(("hpfs_hpbmap: offset too big\n"));
return (EFBIG);
}
/*
* Find place and preinitialize AlSec structure
* AlBlk is initialized to contain AlLeafs.
*/
int
hpfs_allocalsec (
struct hpfsmount *hpmp,
lsn_t parlsn,
struct buf **bpp)
{
alsec_t * asp;
struct buf * bp;
lsn_t lsn;
int error;
*bpp = NULL;
error = hpfs_bmfblookup(hpmp, &lsn);
if (error) {
printf("hpfs_allocalsec: CAN'T ALLOC SPACE FOR AlSec\n");
return (error);
}
error = hpfs_bmmarkbusy(hpmp, lsn, 1);
if (error)
return (error);
bp = getblk(hpmp->hpm_devvp, lsn, DEV_BSIZE, 0, 0, 0);
clrbuf(bp);
/* Fill AlSec info */
asp = (alsec_t *) bp->b_data;
asp->as_magic = AS_MAGIC;
asp->as_self = lsn;
asp->as_parent = parlsn;
/* Fill AlBlk */
asp->as_ab.ab_flag = 0;
asp->as_ab.ab_busycnt = 0;
asp->as_ab.ab_freecnt = 0x28;
asp->as_ab.ab_freeoff = sizeof(alblk_t);
*bpp = bp;
return (0);
}
/*
* Split AlSec structure into new allocated:
* allocate new AlSec; then move second half of asp's entries in
* into it; set proper flags.
*
* IF AlSec CONTAINS AlNodes, THEN YOU ALMOST EVERYTIME HAVE TO
* FIX LAST AlNode in OLD AlSec (NEXTOFF TO BE 0xFFFFFFFF).
* TOGETHER WITH FIXING ALL CHILDREN'S AlSecs (THEY HAVE GOT NEW PARENT).
*/
int
hpfs_splitalsec (
struct hpfsmount *hpmp,
alsec_t *asp,
alsec_t **naspp,
struct buf **nbpp)
{
alsec_t *nasp;
struct buf *nbp;
alblk_t *abp;
alblk_t *nabp;
int error, n1, n2, sz;
error = hpfs_allocalsec(hpmp, asp->as_parent, &nbp);
if (error)
return (error);
nasp = (alsec_t *)nbp->b_data;
nabp = &nasp->as_ab;
abp = &asp->as_ab;
n1 = (abp->ab_busycnt + 1) / 2;
n2 = (abp->ab_busycnt - n1);
sz = (abp->ab_flag & AB_NODES) ? sizeof(alnode_t) : sizeof(alleaf_t);
bcopy((caddr_t)abp + sizeof(alblk_t) + n1 * sz,
(caddr_t)nabp + sizeof(alblk_t), n2 * sz);
nabp->ab_flag = abp->ab_flag;
nabp->ab_busycnt = n2;
nabp->ab_freecnt = (0x1e0 / sz - n2);
nabp->ab_freeoff += n2 * sz;
abp->ab_busycnt -= n1;
abp->ab_freecnt += n1;
abp->ab_freeoff -= n1 * sz;
*naspp = nasp;
*nbpp = nbp;
return (0);
}
/*
* Try to concatenate two AlSec's
*
* Moves all entries from AlSec corresponding (as1p, aanp[1]) into
* corresponding aanp[0] one. If not enought space, then return ENOSPC.
*
* WARNING! YOU HAVE TO FIX aanp VALUES YOURSELF LATER:
* aanp[0].an_nextoff = aanp[1].an_nextoff;
*/
int
hpfs_concatalsec (
struct hpfsmount *hpmp,
alsec_t *as0p,
alsec_t *as1p,
alnode_t *aanp)
{
alblk_t *ab0p;
alblk_t *ab1p;
int sz;
dprintf(("hpfs_concatalsec: AlSecs at 0x%x and 0x%x \n",
as0p->as_self,as1p->as_self));
ab0p = &as0p->as_ab;
ab1p = &as1p->as_ab;
sz = (ab0p->ab_flag & AB_NODES) ? sizeof(alnode_t) : sizeof(alleaf_t);
if (ab0p->ab_freecnt > ab1p->ab_busycnt) {
/*
* Concatenate AlSecs
*/
if (ab0p->ab_flag & AB_NODES)
AB_LASTANP(ab0p)->an_nextoff = aanp[0].an_nextoff;
bcopy (AB_ALNODE(ab1p), AB_FREEANP(ab0p),
ab1p->ab_busycnt * sz);
AB_ADDNREC(ab0p, sz, ab1p->ab_busycnt);
return (0);
} else {
/* Not enought space to concatenate */
return (ENOSPC);
}
}
/*
* Transform AlBlk structure into new allocated
* AlSec.
*
* DOESN'T SET AlSec'S PARENT LSN.
*/
int
hpfs_alblk2alsec (
struct hpfsmount *hpmp,
alblk_t *abp,
alsec_t **naspp,
struct buf **nbpp)
{
alsec_t *nasp;
alblk_t *nabp;
struct buf *nbp;
int error, sz;
error = hpfs_allocalsec(hpmp, 0, &nbp);
if (error)
return (error);
nasp = (alsec_t *)nbp->b_data;
nabp = &nasp->as_ab;
sz = (abp->ab_flag & AB_NODES) ? sizeof(alnode_t) : sizeof(alleaf_t);
bcopy (abp, nabp, sizeof(alblk_t) + sz * abp->ab_busycnt);
nabp->ab_freecnt = 0x1e0 / sz - nabp->ab_busycnt;
*naspp = nasp;
*nbpp = nbp;
return (0);
}
/*
* Allocate len blocks and concatenate them to file.
* If we hadn't found contignous run of len blocks, concatenate
* as much as we can, and return.
*
*/
int
hpfs_addextent (
struct hpfsmount *hpmp,
struct hpfsnode *hp,
u_long len)
{
alblk_t *rabp;
alnode_t ranp[2];
alleaf_t al;
int error;
u_long pf;
/*
* We don't know for now start lsn of block
*/
al.al_lsn = ~0;
al.al_len = len;
al.al_off = (hp->h_fn.fn_size + DEV_BSIZE - 1) >> DEV_BSHIFT;
rabp = &hp->h_fn.fn_ab;
/* Init AlBlk if this is first extent */
if (al.al_off == 0) {
lsn_t nlsn;
u_long nlen;
dprintf(("hpfs_addextent: init AlBlk in root\n"));
rabp->ab_busycnt = 0;
rabp->ab_freecnt = 0x8;
rabp->ab_freeoff = sizeof(alblk_t);
rabp->ab_flag = 0;
error = hpfs_bmlookup (hpmp, 0, hp->h_no + 1, al.al_len, &nlsn, &nlen);
if (error)
return (error);
error = hpfs_bmmarkbusy(hpmp, nlsn, nlen);
if (error)
return (error);
dprintf(("hpfs_addextent: new: 0x%x 0x%lx, ", nlsn, nlen));
AL_SET(AB_FREEALP(rabp), al.al_off, nlen, nlsn);
AB_ADDAL(rabp);
al.al_off += nlen;
al.al_len -= nlen;
}
retry:
dprintf(("hpfs_addextent: AlBlk: [0x%x, 0x%x, 0x%x] need: 0x%x\n",
rabp->ab_freecnt, rabp->ab_busycnt, rabp->ab_flag, al.al_len));
while ((al.al_len) && (rabp->ab_freecnt > 0)) {
if (rabp->ab_flag & AB_NODES) {
alnode_t *anp;
/*
* This is level containing AlNodes, so try to
* insert recursively into last entry.
*/
anp = AB_LASTANP(rabp);
dprintf(("hpfs_addextent: AlNode: [0x%x,0x%x] \n",
anp->an_nextoff,anp->an_lsn));
/*
* Try to insert...
*/
error = hpfs_addextentr (hpmp, anp->an_lsn, &al, ranp, &pf);
if (error) {
printf("hpfs_addextent: FAILED %d\n",error);
return (error);
}
switch (pf) {
case AE_SPLIT:
dprintf(("hpfs_addextent: successful (split)\n"));
/*
* Then hpfs_addextentr has split tree below, now
* we need to fix this level. Particulary:
* fix last AlNode and add another one.
*/
bcopy(ranp, AB_LASTANP(rabp), sizeof(alnode_t) * 2);
AB_ADDAN(rabp);
break;
default:
case AE_DONE:
dprintf(("hpfs_addextent: successful\n"));
break;
}
} else {
alleaf_t *alp;
alp = AB_LASTALP(rabp);
dprintf(("hpfs_addextent: AlLeaf: [0x%x,0x%x,0x%x] \n",
alp->al_off,alp->al_len,alp->al_lsn));
/* Check if we trying to add in right place */
if (alp->al_off + alp->al_len == al.al_off) {
lsn_t nlsn;
u_long nlen;
/*
* Search bitmap for block begining from
* alp->al_lsn + alp->al_len and long of ralp->al_len
*/
error = hpfs_bmlookup (hpmp, 0,
alp->al_lsn + alp->al_len, al.al_len, &nlsn, &nlen);
if (error)
return (error);
error = hpfs_bmmarkbusy(hpmp, nlsn, nlen);
if (error)
return (error);
dprintf(("hpfs_addextent: new: 0x%x 0x%lx, ", nlsn, nlen));
if (alp->al_lsn + alp->al_len == nlsn) {
dprintf(("extended existed leaf\n"));
alp->al_len += nlen;
} else {
dprintf(("created new leaf\n"));
AL_SET(AB_FREEALP(rabp), al.al_off, nlen, nlsn);
AB_ADDAL(rabp);
}
al.al_off += nlen;
al.al_len -= nlen;
} else {
printf("hpfs_addextent: INTERNAL INCONSISTENCE\n");
return (EINVAL);
}
}
}
/*
* Move AlBlk contain to new AlSec (it will fit more
* entries) if overflowed (no more free entries).
*/
if (rabp->ab_freecnt <= 0) {
struct buf *nbp;
alsec_t * nrasp;
dprintf(("hpfs_addextent: overflow, convt\n"));
/*
* Convert AlBlk to new AlSec, it will set
* AB_FNPARENT also.
*/
rabp->ab_flag |= AB_FNPARENT;
error = hpfs_alblk2alsec (hpmp, rabp, &nrasp, &nbp);
if (error) {
printf("hpfs_addextent: CAN'T CONVT\n");
return (error);
}
nrasp->as_parent = hp->h_no;
/*
* Scan all childrens (if exist), set new parent and
* clean their AB_FNPARENT flag.
*/
if (rabp->ab_flag & AB_NODES) {
int i;
alsec_t * asp;
alnode_t * anp;
struct buf * bp;
anp = AB_ALNODE(rabp);
for (i=0; i<rabp->ab_busycnt; i++) {
error = hpfs_breadalsec(hpmp, anp->an_lsn, &bp);
if (error)
return (error);
asp = (alsec_t *)bp->b_data;
asp->as_ab.ab_flag &= ~AB_FNPARENT;
asp->as_parent = nrasp->as_self;
bdwrite(bp);
anp ++;
}
}
/* Convert AlBlk to contain AlNodes */
rabp->ab_flag = AB_NODES;
rabp->ab_busycnt = 0;
rabp->ab_freecnt = 0xC;
rabp->ab_freeoff = sizeof(alblk_t);
/* Add AlNode for new allocated AlSec */
AN_SET(AB_FREEANP(rabp), ~0, nrasp->as_self);
AB_ADDAN(rabp);
bdwrite(nbp);
}
if (al.al_len) {
dprintf(("hpfs_addextent: root retry\n"));
goto retry;
}
return (0);
}
/*
* Descent down to the end of tree, then search for
* ralp->len contignous run begining from last run's end and
* concatenate new block! If we can't find one, then...
*/
int
hpfs_addextentr (
struct hpfsmount *hpmp, /* Mix info */
lsn_t rlsn, /* LSN containing AlSec */
alleaf_t *ralp, /* AlLeaf to insert */
alnode_t *ranp, /* New AlNodes' values */
u_long *resp) /* Mix returning info */
{
struct buf *rbp;
alsec_t *rasp;
alblk_t *rabp;
alleaf_t *alp;
alnode_t *anp;
int error;
u_long pf;
u_long wb;
*resp = 0;
dprintf(("hpfs_addextentr: AlSec at 0x%x\n", rlsn));
error = hpfs_breadalsec(hpmp, rlsn, &rbp);
if (error)
return (error);
rasp = (alsec_t *)rbp->b_data;
rabp = &rasp->as_ab;
wb = 0;
dprintf(("hpfs_addextentr: AlBlk: [0x%x, 0x%x, 0x%x]\n",
rabp->ab_freecnt, rabp->ab_busycnt, rabp->ab_flag));
while ((ralp->al_len) && (rabp->ab_freecnt > 0)) {
if (rabp->ab_flag & AB_NODES) {
/*
* This is level containing AlNodes, so try to
* insert recursively into last entry.
*/
anp = AB_LASTANP(rabp);
dprintf(("hpfs_addextentr: AlNode: [0x%x,0x%x] \n",
anp->an_nextoff,anp->an_lsn));
/*
* Try to insert...
*/
error = hpfs_addextentr (hpmp, anp->an_lsn, ralp, ranp, &pf);
if (error) {
printf("hpfs_addextentr: FAILED %d\n",error);
goto fail;
}
switch (pf) {
case AE_SPLIT:
dprintf(("hpfs_addextentr: successful (split)\n"));
/*
* Then hpfs_addextentr has split tree below, now
* we need to fix this level. Particulary:
* fix last AlNode and add another one.
*/
bcopy(ranp, AB_LASTANP(rabp), sizeof(alnode_t) * 2);
AB_ADDAN(rabp);
wb = 1;
break;
default:
case AE_DONE:
dprintf(("hpfs_addextentr: successful\n"));
break;
}
} else {
alp = AB_LASTALP(rabp);
dprintf(("hpfs_addextentr: AlLeaf: [0x%x,0x%x,0x%x] \n",
alp->al_off,alp->al_len,alp->al_lsn));
/* Check if we trying to add in right place */
if (alp->al_off + alp->al_len == ralp->al_off) {
lsn_t nlsn;
u_long nlen;
/*
* Search bitmap for block begining from
* alp->al_lsn + alp->al_len and long of ralp->al_len
*/
error = hpfs_bmlookup (hpmp, 0,
alp->al_lsn + alp->al_len, ralp->al_len, &nlsn, &nlen);
if (error)
goto fail;
error = hpfs_bmmarkbusy(hpmp, nlsn, nlen);
if (error)
goto fail;
dprintf(("hpfs_addextentr: new: 0x%x 0x%lx, ", nlsn, nlen));
/*
* If ending of existed entry fits the
* begining of the extent being added,
* then we add concatenate two extents.
*/
if (alp->al_lsn + alp->al_len == nlsn) {
dprintf(("concat\n"));
alp->al_len += nlen;
} else {
dprintf(("created new leaf\n"));
AL_SET(AB_FREEALP(rabp), ralp->al_off, nlen, nlsn);
AB_ADDAL(rabp);
}
ralp->al_len -= nlen;
ralp->al_off += nlen;
} else {
printf("hpfs_addextentr: INTERNAL INCONSISTENCE\n");
error = (EINVAL);
goto fail;
}
}
}
/*
* Split AlBlk if overflowed.
*/
if (rabp->ab_freecnt <= 0) {
struct buf *nbp;
alsec_t * nrasp;
dprintf(("hpfs_addextentr: overflow, split\n"));
error = hpfs_splitalsec (hpmp, rasp, &nrasp, &nbp);
if (error) {
printf("hpfs_addextent: CAN'T SPLIT\n");
goto fail;
}
if (rabp->ab_flag & AB_NODES) {
int i;
alsec_t * asp;
alnode_t * anp;
struct buf * bp;
ranp[0].an_nextoff =
AB_LASTANP(&rasp->as_ab)->an_nextoff;
/* We need to set left subtree's last entry
* offset to 0xFFFFFFFF for OS/2 to be able
* to read our files. It treats absence of
* 0xFFFFFFFF as error.
*/
AB_LASTANP(&rasp->as_ab)->an_nextoff = ~0;
/* We need to fix new allocated AlSec's
* children, becouse their parent has changed.
*/
anp = AB_ALNODE(&nrasp->as_ab);
for (i=0; i<nrasp->as_ab.ab_busycnt; i++) {
error = hpfs_breadalsec(hpmp, anp->an_lsn, &bp);
if (error) {
brelse(nbp);
goto fail;
}
asp = (alsec_t *)bp->b_data;
asp->as_parent = nrasp->as_self;
bdwrite(bp);
anp ++;
}
} else {
ranp[0].an_nextoff =
AB_ALLEAF(&nrasp->as_ab)->al_off;
}
ranp[0].an_lsn = rasp->as_self;
ranp[1].an_nextoff = ~0;
ranp[1].an_lsn = nrasp->as_self;
bdwrite(nbp);
*resp = AE_SPLIT;
wb = 1;
}
if (wb)
bdwrite (rbp);
else
brelse(rbp);
return (0);
fail:
brelse(rbp);
return (error);
}
/*
* Recursive routine walking down the b-tree and deallocating all
* extents above bn. Returns *resp != 0 if alblk was totally
* deallocated and may be freed. Tries to keep b-tree.
*
* (XXXX) NOTE! THIS ROUTINE WILL NEVER DECREMENT DEPTH OF
* THE TREE.
*/
int
hpfs_truncatealblk (
struct hpfsmount *hpmp,
alblk_t *abp,
lsn_t bn,
int *resp)
{
int error;
alleaf_t *alp;
alnode_t *anp;
alsec_t *asp;
struct buf *bp;
dprintf(("hpfs_truncatealblk: AlBlk: [0x%x,0x%x, 0x%x]\n",
abp->ab_freecnt, abp->ab_busycnt, abp->ab_flag));
if (abp->ab_flag & AB_NODES) {
/*
* Scan array of AlNodes backward,
* diving in recursion if needed
*/
anp = AB_LASTANP(abp);
while (abp->ab_busycnt && (bn <= anp->an_nextoff)) {
dprintf(("hpfs_truncatealblk: AlNode: [0x%x,0x%x] \n",
anp->an_nextoff,anp->an_lsn));
error = hpfs_breadalsec(hpmp, anp->an_lsn, &bp);
if (error)
return (error);
asp = (alsec_t *)bp->b_data;
error = hpfs_truncatealblk (hpmp,
&asp->as_ab, bn, resp);
if (error) {
brelse(bp);
return (error);
}
if (*resp) {
brelse (bp);
error = hpfs_bmmarkfree(hpmp,
anp->an_lsn, 1);
if (error)
return (error);
AB_RMAN(abp);
anp --;
} else {
/*
* We have deallocated some entries, some space
* migth been freed, then try to concat two
* last AlSec.
*/
anp->an_nextoff = ~0;
if (abp->ab_busycnt >= 2) {
alsec_t *as0p;
struct buf *b0p;
error = hpfs_breadalsec(hpmp,
(anp-1)->an_lsn, &b0p);
if (error)
return (error);
as0p = (alsec_t *)b0p->b_data;
error = hpfs_concatalsec(hpmp,
as0p, asp, anp - 1);
if (error == ENOSPC) {
/* Not enought space */
brelse (b0p);
bdwrite (bp);
} else if (error == 0) {
/* All OK */
(anp-1)->an_nextoff = anp->an_nextoff;
bdwrite (b0p);
brelse (bp);
error = hpfs_bmmarkfree(hpmp,
anp->an_lsn, 1);
if (error)
return (error);
AB_RMAN(abp);
} else {
/* True error */
brelse (b0p);
brelse (bp);
return (error);
}
} else {
/* Nowhere to concatenate */
bdwrite (bp);
}
/* There can not be any more entries
* over greater bn, becouse last AlSec
* wasn't freed totally. So go out.
*/
break;
}
}
if (abp->ab_busycnt == 0)
*resp = 1;
else
*resp = 0;
} else {
/*
* Scan array of AlLeafs backward,
* free all above bn.
*/
alp = AB_LASTALP(abp);
while (abp->ab_busycnt && (bn < alp->al_off + alp->al_len)){
dprintf(("hpfs_truncatealblk: AlLeaf: [0x%x,0x%x,0x%x] \n",
alp->al_off,alp->al_len,alp->al_lsn));
if (bn <= alp->al_off) {
error = hpfs_bmmarkfree(hpmp, alp->al_lsn,
alp->al_len);
if (error)
return (error);
AB_RMAL(abp);
alp --;
} else if ((bn > alp->al_off) &&
(bn < alp->al_off + alp->al_len)){
error = hpfs_bmmarkfree(hpmp,
alp->al_lsn + bn - alp->al_off,
alp->al_len - bn + alp->al_off);
if (error)
return (error);
alp->al_len = bn - alp->al_off;
break;
} else
break;
}
}
/* Signal parent deallocation, if need */
if (abp->ab_busycnt == 0)
*resp = 1;
else
*resp = 0;
return (0);
}

View File

@ -1,43 +0,0 @@
/*-
* Copyright (c) 1998, 1999 Semen Ustimenko (semenu@FreeBSD.org)
* 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.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
*
* $FreeBSD$
*/
#ifndef _HPFS_IOCTL_H_
#define _HPFS_IOCTL_H_
#include <sys/ioccom.h>
struct hpfs_rdea {
u_long ea_no;
u_long ea_sz;
void * ea_data;
};
#define HPFSIOCGEANUM _IOR('H', 0, u_long) /* Get EA number */
#define HPFSIOCGEASZ _IOWR('H', 1, u_long) /* Get EA size */
#define HPFSIOCRDEA _IOWR('H', 2, struct hpfs_rdea) /* Read EA */
#endif

View File

@ -1,213 +0,0 @@
/*-
* Copyright (c) 1998, 1999 Semen Ustimenko (semenu@FreeBSD.org)
* 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.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
*
* $FreeBSD$
*/
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/proc.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/vnode.h>
#include <sys/mount.h>
#include <sys/namei.h>
#include <sys/malloc.h>
#include <sys/bio.h>
#include <sys/buf.h>
#include <fs/hpfs/hpfs.h>
#include <fs/hpfs/hpfsmount.h>
#include <fs/hpfs/hpfs_subr.h>
int hpfs_removedirent (struct hpfsmount *, lsn_t, char *, int, int *);
/*
* This routine traverse the b+ tree representing directory
* looking for file named 'name'. Returns buf struct and hpfsdirent
* pointer. Calling routine is supposed to brelse buffer.
* name is supposed in Unix encodeing.
*/
int
hpfs_genlookupbyname (
struct hpfsnode *dhp,
char *name,
int namelen,
struct buf **bpp,
struct hpfsdirent **depp)
{
struct hpfsmount *hpmp = dhp->h_hpmp;
struct buf *bp;
struct dirblk *dp;
struct hpfsdirent *dep;
lsn_t lsn;
int error, res;
dprintf(("hpfs_genlookupbyname(0x%x, %s (%d)): \n",
dhp->h_no, name, namelen));
lsn = ((alleaf_t *)dhp->h_fn.fn_abd)->al_lsn;
dive:
error = hpfs_breaddirblk (hpmp, lsn, &bp);
if (error)
return (error);
dp = (struct dirblk *) bp->b_data;
dep = D_DIRENT(dp);
while(!(dep->de_flag & DE_END)) {
dprintf(("no: 0x%x, size: %d, name: %2d:%.*s, flag: 0x%x\n",
dep->de_fnode, dep->de_size, dep->de_namelen,
dep->de_namelen, dep->de_name, dep->de_flag));
res = hpfs_cmpfname(hpmp, name, namelen,
dep->de_name, dep->de_namelen, dep->de_cpid);
if (res == 0) {
*bpp = bp;
*depp = dep;
return (0);
} else if (res < 0)
break;
dep = (hpfsdirent_t *)(((caddr_t)dep) + dep->de_reclen);
}
if (dep->de_flag & DE_DOWN) {
lsn = DE_DOWNLSN(dep);
brelse(bp);
goto dive;
}
brelse(bp);
return (ENOENT);
}
int
hpfs_makefnode (
struct vnode * dvp,
struct vnode ** vpp,
struct componentname *cnp,
struct vattr *vap)
{
#ifdef HPFS_DEBUG
register struct hpfsnode *dhp = VTOHP(dvp);
dprintf(("hpfs_makefnode(0x%x, %s, %ld): \n",
dhp->h_no, cnp->cn_nameptr, cnp->cn_namelen));
#endif
return (EOPNOTSUPP);
}
int
hpfs_removedirent (
struct hpfsmount *hpmp,
lsn_t lsn,
char *name,
int namelen,
int *retp)
{
#if 0
struct buf *bp;
dirblk_t *dbp;
struct hpfsdirent *dep;
int deoff;
int error, ret;
dprintf(("hpfs_removedirent(0x%x, %.*s, %d): \n",
lsn, namelen, name, namelen));
error = hpfs_breaddirblk (hpmp, lsn, &bp);
if (error)
return (error);
dbp = (dirblk_t *) bp->b_data;
deoff = sizeof(dirblk_t);
dep = DB_DIRENT(dbp);
while(!(dep->de_flag & DE_END)) {
dprintf(("no: 0x%x, size: %d, name: %2d:%.*s, flag: 0x%x\n",
dep->de_fnode, dep->de_size, dep->de_namelen,
dep->de_namelen, dep->de_name, dep->de_flag));
res = hpfs_cmpfname(hpmp, name, namelen,
dep->de_name, dep->de_namelen, dep->de_cpid);
if (res == 0) {
if (dep->de_flag & DE_DOWN) {
/*XXXXXX*/
} else {
/* XXX we can copy less */
bcopy (DE_NEXTDE(dep), dep, DB_BSIZE - deoff - dep->de_reclen);
dbp->d_freeoff -= dep->de_reclen;
*retp = 0;
}
bdwrite (bp);
return (0);
} else if (res < 0)
break;
deoff += dep->de_reclen;
dep = DB_NEXTDE(dep);
}
if (dep->de_flag & DE_DOWN) {
error = hpfs_removede (hpmp, DE_DOWNLSN(dep), name, namelen, &ret);
if (error) {
brelse (bp);
return (error);
}
if (ret == 0) {
if (deoff > sizeof (dirblk_t)) {
} else if (deoff + dep->de_reclen < dbp->db_freeoff) {
}
}
} else {
error = ENOENT;
}
brelse (bp);
return (error);
#endif
return (EOPNOTSUPP);
}
int
hpfs_removefnode (
struct vnode * dvp,
struct vnode * vp,
struct componentname *cnp)
{
#ifdef HPFS_DEBUG
register struct hpfsnode *dhp = VTOHP(dvp);
register struct hpfsnode *hp = VTOHP(vp);
dprintf(("hpfs_removefnode(0x%x, 0x%x, %s, %ld): \n",
dhp->h_no, hp->h_no, cnp->cn_nameptr, cnp->cn_namelen));
#endif
return (EOPNOTSUPP);
}

View File

@ -1,869 +0,0 @@
/*-
* Copyright (c) 1998, 1999 Semen Ustimenko (semenu@FreeBSD.org)
* 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.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
*
* $FreeBSD$
*/
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/proc.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/vnode.h>
#include <sys/mount.h>
#include <sys/namei.h>
#include <sys/malloc.h>
#include <sys/bio.h>
#include <sys/buf.h>
#include <fs/hpfs/hpfs.h>
#include <fs/hpfs/hpfsmount.h>
#include <fs/hpfs/hpfs_subr.h>
u_long
hpfs_checksum(
u_int8_t *object,
int size)
{
register int i;
u_long csum=0L;
for (i=0; i < size; i++) {
csum += (u_long) *object++;
csum = (csum << 7) + (csum >> (25));
}
return (csum);
}
void
hpfs_bmdeinit(
struct hpfsmount *hpmp)
{
struct buf *bp;
int i;
dprintf(("hpmp_bmdeinit: "));
if (!(hpmp->hpm_mp->mnt_flag & MNT_RDONLY)) {
/*
* Write down BitMap.
*/
for (i=0; i<hpmp->hpm_dbnum; i++) {
dprintf(("[%d: 0x%x] ", i, hpmp->hpm_bmind[i]));
bp = getblk(hpmp->hpm_devvp, hpmp->hpm_bmind[i],
BMSIZE, 0, 0, 0);
clrbuf(bp);
bcopy(hpmp->hpm_bitmap + BMSIZE * i, bp->b_data,
BMSIZE);
bwrite(bp);
}
}
free(hpmp->hpm_bitmap,M_HPFSMNT);
free(hpmp->hpm_bmind,M_HPFSMNT);
dprintf(("\n"));
}
/*
* Initialize BitMap management, includes calculation of
* available blocks number.
*/
int
hpfs_bminit(
struct hpfsmount *hpmp)
{
struct buf *bp;
int error, i, k;
u_long dbavail;
dprintf(("hpfs_bminit: "));
hpmp->hpm_dbnum = (hpmp->hpm_su.su_btotal + 0x3FFF) / 0x4000;
dprintf(("0x%lx data bands, ", hpmp->hpm_dbnum));
hpmp->hpm_bmind = malloc(hpmp->hpm_dbnum * sizeof(lsn_t),
M_HPFSMNT, M_WAITOK);
hpmp->hpm_bitmap = malloc(hpmp->hpm_dbnum * BMSIZE,
M_HPFSMNT, M_WAITOK);
error = bread(hpmp->hpm_devvp, hpmp->hpm_su.su_bitmap.lsn1,
((hpmp->hpm_dbnum + 0x7F) & ~(0x7F)) << 2, NOCRED, &bp);
if (error) {
brelse(bp);
free(hpmp->hpm_bitmap, M_HPFSMNT);
free(hpmp->hpm_bmind, M_HPFSMNT);
dprintf((" error %d\n", error));
return (error);
}
bcopy(bp->b_data, hpmp->hpm_bmind, hpmp->hpm_dbnum * sizeof(lsn_t));
brelse(bp);
/*
* Read in all BitMap
*/
for (i=0; i<hpmp->hpm_dbnum; i++) {
dprintf(("[%d: 0x%x] ", i, hpmp->hpm_bmind[i]));
error = bread(hpmp->hpm_devvp, hpmp->hpm_bmind[i],
BMSIZE, NOCRED, &bp);
if (error) {
brelse(bp);
free(hpmp->hpm_bitmap, M_HPFSMNT);
free(hpmp->hpm_bmind, M_HPFSMNT);
dprintf((" error %d\n", error));
return (error);
}
bcopy(bp->b_data, hpmp->hpm_bitmap + BMSIZE * i, BMSIZE);
brelse(bp);
}
/*
* Look througth BitMap and count free bits
*/
dbavail = 0;
for (i=0; i < hpmp->hpm_su.su_btotal >> 5; i++) {
register u_int32_t mask;
for (k=0, mask=1; k < 32; k++, mask<<=1)
if(((u_int32_t *)hpmp->hpm_bitmap)[i] & mask)
dbavail ++;
}
hpmp->hpm_bavail = dbavail;
return (0);
}
int
hpfs_cmpfname (
struct hpfsmount *hpmp,
char * uname,
int ulen,
char * dname,
int dlen,
u_int16_t cp)
{
register int i, res;
for (i = 0; i < ulen && i < dlen; i++) {
res = hpfs_toupper(hpmp, hpfs_u2d(hpmp, uname[i]), cp) -
hpfs_toupper(hpmp, dname[i], cp);
if (res)
return res;
}
return (ulen - dlen);
}
int
hpfs_cpstrnnicmp (
struct hpfsmount *hpmp,
char * str1,
int str1len,
u_int16_t str1cp,
char * str2,
int str2len,
u_int16_t str2cp)
{
int i, res;
for (i = 0; i < str1len && i < str2len; i++) {
res = (int)hpfs_toupper(hpmp, ((u_char *)str1)[i], str1cp) -
(int)hpfs_toupper(hpmp, ((u_char *)str2)[i], str2cp);
if (res)
return res;
}
return (str1len - str2len);
}
int
hpfs_cpload (
struct hpfsmount *hpmp,
struct cpiblk *cpibp,
struct cpdblk *cpdbp)
{
struct buf *bp;
struct cpdsec * cpdsp;
int error, i;
error = bread(hpmp->hpm_devvp, cpibp->b_cpdsec, DEV_BSIZE, NOCRED, &bp);
if (error) {
brelse(bp);
return (error);
}
cpdsp = (struct cpdsec *)bp->b_data;
for (i=cpdsp->d_cpfirst; i<cpdsp->d_cpcnt; i++) {
if (cpdsp->d_cpdblk[i].b_cpid == cpibp->b_cpid) {
bcopy(cpdsp->d_cpdblk + i, cpdbp,
sizeof(struct cpdblk));
brelse(bp);
return (0);
}
}
brelse(bp);
return (ENOENT);
}
/*
* Initialize Code Page information management.
* Load all copdepages in memory.
*/
int
hpfs_cpinit (
struct mount *mp,
struct hpfsmount *hpmp)
{
struct buf *bp;
int error, i;
lsn_t lsn;
int cpicnt;
struct cpisec * cpisp;
struct cpiblk * cpibp;
struct cpdblk * cpdbp;
dprintf(("hpfs_cpinit: \n"));
error = vfs_copyopt(mp->mnt_optnew, "d2u", hpmp->hpm_d2u,
sizeof hpmp->hpm_d2u);
if (error == ENOENT)
for (i=0x0; i<0x80;i++)
hpmp->hpm_d2u[i] = i + 0x80;
else if (error)
return (error);
error = vfs_copyopt(mp->mnt_optnew, "u2d", hpmp->hpm_u2d,
sizeof hpmp->hpm_u2d);
if (error == ENOENT)
for (i=0x0; i<0x80;i++)
hpmp->hpm_u2d[i] = i + 0x80;
else if (error)
return (error);
cpicnt = hpmp->hpm_sp.sp_cpinum;
hpmp->hpm_cpdblk = malloc(cpicnt * sizeof(struct cpdblk),
M_HPFSMNT, M_WAITOK);
cpdbp = hpmp->hpm_cpdblk;
lsn = hpmp->hpm_sp.sp_cpi;
while (cpicnt > 0) {
error = bread(hpmp->hpm_devvp, lsn, DEV_BSIZE, NOCRED, &bp);
if (error) {
brelse(bp);
return (error);
}
cpisp = (struct cpisec *)bp->b_data;
cpibp = cpisp->s_cpi;
for (i=0; i<cpisp->s_cpicnt; i++, cpicnt --, cpdbp++, cpibp++) {
dprintf(("hpfs_cpinit: Country: %d, CP: %d (%d)\n",
cpibp->b_country, cpibp->b_cpid,
cpibp->b_vcpid));
error = hpfs_cpload(hpmp, cpibp, cpdbp);
if (error) {
brelse(bp);
return (error);
}
}
lsn = cpisp->s_next;
brelse(bp);
}
return (0);
}
int
hpfs_cpdeinit (
struct hpfsmount *hpmp)
{
dprintf(("hpmp_cpdeinit: "));
free(hpmp->hpm_cpdblk,M_HPFSMNT);
return (0);
}
/*
* Lookup for a run of blocks.
*/
int
hpfs_bmlookup (
struct hpfsmount *hpmp,
u_long flags, /* 1 means we want right len blocks in run, not less */
lsn_t lsn, /* We want near this one */
u_long len, /* We want such long */
lsn_t *lsnp, /* We got here */
u_long *lenp) /* We got this long */
{
u_int32_t * bitmap;
register u_int32_t mask;
int i,k;
int cband, vcband;
u_int bandsz;
int count;
dprintf(("hpfs_bmlookup: lsn: 0x%x, len 0x%lx | Step1\n", lsn, len));
if (lsn > hpmp->hpm_su.su_btotal) {
printf("hpfs_bmlookup: OUT OF VOLUME\n");
return ENOSPC;
}
if (len > hpmp->hpm_bavail) {
printf("hpfs_bmlookup: OUT OF SPACE\n");
return ENOSPC;
}
i = lsn >> 5;
k = lsn & 0x1F;
mask = 1 << k;
bitmap = (u_int32_t *)hpmp->hpm_bitmap + i;
if (*bitmap & mask) {
*lsnp = lsn;
*lenp = 0;
for (; k < 32; k++, mask<<=1) {
if (*bitmap & mask)
(*lenp) ++;
else {
if (flags & 1)
goto step2;
else
return (0);
}
if (*lenp == len)
return (0);
}
bitmap++;
i++;
for (; i < hpmp->hpm_su.su_btotal >> 5; i++, bitmap++) {
for (k=0, mask=1; k < 32; k++, mask<<=1) {
if (*bitmap & mask)
(*lenp) ++;
else {
if (flags & 1)
goto step2;
else
return (0);
}
if (*lenp == len)
return (0);
}
}
return (0);
}
step2:
/*
* Lookup all bands begining from cband, lookup for first block
*/
cband = (lsn >> 14);
dprintf(("hpfs_bmlookup: Step2: band 0x%x (0x%lx)\n",
cband, hpmp->hpm_dbnum));
for (vcband = 0; vcband < hpmp->hpm_dbnum; vcband ++, cband++) {
cband = cband % hpmp->hpm_dbnum;
bandsz = min (hpmp->hpm_su.su_btotal - (cband << 14), 0x4000);
dprintf(("hpfs_bmlookup: band: %d, sz: 0x%x\n", cband, bandsz));
bitmap = (u_int32_t *)hpmp->hpm_bitmap + (cband << 9);
*lsnp = cband << 14;
*lenp = 0;
count = 0;
for (i=0; i < bandsz >> 5; i++, bitmap++) {
for (k=0, mask=1; k < 32; k++, mask<<=1) {
if (*bitmap & mask) {
if (count) {
(*lenp) ++;
} else {
count = 1;
*lsnp = (cband << 14) + (i << 5) + k;
*lenp = 1;
}
} else {
if ((*lenp) && !(flags & 1)) {
return (0);
} else {
count = 0;
}
}
if (*lenp == len)
return (0);
}
}
if (cband == hpmp->hpm_dbnum - 1) {
if ((*lenp) && !(flags & 1)) {
return (0);
} else {
count = 0;
}
}
}
return (ENOSPC);
}
/*
* Lookup a single free block. XXX Need locking on BitMap operations
* VERY STUPID ROUTINE!!!
*/
int
hpfs_bmfblookup (
struct hpfsmount *hpmp,
lsn_t *lp)
{
u_int32_t * bitmap;
int i,k;
dprintf(("hpfs_bmfblookup: "));
bitmap = (u_int32_t *)hpmp->hpm_bitmap;
for (i=0; i < hpmp->hpm_su.su_btotal >> 5; i++, bitmap++) {
k = ffs(*bitmap);
if (k) {
*lp = (i << 5) + k - 1;
dprintf((" found: 0x%x\n",*lp));
return (0);
}
}
return (ENOSPC);
}
/*
* Mark contignous block of blocks.
*/
int
hpfs_bmmark (
struct hpfsmount *hpmp,
lsn_t bn,
u_long bl,
int state)
{
u_int32_t * bitmap;
int i, didprint = 0;
dprintf(("hpfs_bmmark(0x%x, 0x%lx, %d): \n",bn,bl, state));
if ((bn > hpmp->hpm_su.su_btotal) || (bn+bl > hpmp->hpm_su.su_btotal)) {
printf("hpfs_bmmark: MARKING OUT OF VOLUME\n");
return 0;
}
bitmap = (u_int32_t *)hpmp->hpm_bitmap;
bitmap += bn >> 5;
while (bl > 0) {
for (i = bn & 0x1F; (i < 0x20) && (bl > 0) ; i++, bl--) {
if (state) {
if ( *bitmap & (1 << i)) {
if (!didprint) {
printf("hpfs_bmmark: ALREADY FREE\n");
didprint = 1;
}
} else
hpmp->hpm_bavail++;
*bitmap |= (1 << i);
} else {
if ((~(*bitmap)) & (1 << i)) {
if (!didprint) {
printf("hpfs_bmmark: ALREADY BUSY\n");
didprint = 1;
}
} else
hpmp->hpm_bavail--;
*bitmap &= ~(1 << i);
}
}
bn = 0;
bitmap++;
}
return (0);
}
int
hpfs_validateparent (
struct hpfsnode *hp)
{
struct hpfsnode *dhp;
struct vnode *dvp;
struct hpfsmount *hpmp = hp->h_hpmp;
struct buf *bp;
struct dirblk *dp;
struct hpfsdirent *dep;
lsn_t lsn, olsn;
int level, error;
dprintf(("hpfs_validatetimes(0x%x): [parent: 0x%x] ",
hp->h_no, hp->h_fn.fn_parent));
if (hp->h_no == hp->h_fn.fn_parent) {
dhp = hp;
} else {
error = VFS_VGET(hpmp->hpm_mp, hp->h_fn.fn_parent,
LK_EXCLUSIVE, &dvp);
if (error)
return (error);
dhp = VTOHP(dvp);
}
lsn = ((alleaf_t *)dhp->h_fn.fn_abd)->al_lsn;
olsn = 0;
level = 1;
bp = NULL;
dive:
dprintf(("[dive 0x%x] ", lsn));
if (bp != NULL)
brelse(bp);
error = bread(dhp->h_devvp, lsn, D_BSIZE, NOCRED, &bp);
if (error)
goto failed;
dp = (struct dirblk *) bp->b_data;
if (dp->d_magic != D_MAGIC) {
printf("hpfs_validatetimes: magic doesn't match\n");
error = EINVAL;
goto failed;
}
dep = D_DIRENT(dp);
if (olsn) {
dprintf(("[restore 0x%x] ", olsn));
while(!(dep->de_flag & DE_END) ) {
if((dep->de_flag & DE_DOWN) &&
(olsn == DE_DOWNLSN(dep)))
break;
dep = (hpfsdirent_t *)((caddr_t)dep + dep->de_reclen);
}
if((dep->de_flag & DE_DOWN) && (olsn == DE_DOWNLSN(dep))) {
if (dep->de_flag & DE_END)
goto blockdone;
if (hp->h_no == dep->de_fnode) {
dprintf(("[found] "));
goto readdone;
}
dep = (hpfsdirent_t *)((caddr_t)dep + dep->de_reclen);
} else {
printf("hpfs_validatetimes: ERROR! oLSN not found\n");
error = EINVAL;
goto failed;
}
}
olsn = 0;
while(!(dep->de_flag & DE_END)) {
if(dep->de_flag & DE_DOWN) {
lsn = DE_DOWNLSN(dep);
level++;
goto dive;
}
if (hp->h_no == dep->de_fnode) {
dprintf(("[found] "));
goto readdone;
}
dep = (hpfsdirent_t *)((caddr_t)dep + dep->de_reclen);
}
if(dep->de_flag & DE_DOWN) {
dprintf(("[enddive] "));
lsn = DE_DOWNLSN(dep);
level++;
goto dive;
}
blockdone:
dprintf(("[EOB] "));
olsn = lsn;
lsn = dp->d_parent;
level--;
dprintf(("[level %d] ", level));
if (level > 0)
goto dive; /* undive really */
goto failed;
readdone:
bcopy(dep->de_name,hp->h_name,dep->de_namelen);
hp->h_name[dep->de_namelen] = '\0';
hp->h_namelen = dep->de_namelen;
hp->h_ctime = dep->de_ctime;
hp->h_atime = dep->de_atime;
hp->h_mtime = dep->de_mtime;
hp->h_flag |= H_PARVALID;
dprintf(("[readdone]"));
failed:
dprintf(("\n"));
if (bp != NULL)
brelse(bp);
if (hp != dhp)
vput(dvp);
return (error);
}
struct timespec
hpfstimetounix (
u_long hptime)
{
struct timespec t;
t.tv_nsec = 0;
t.tv_sec = hptime;
return t;
}
/*
* Write down changes done to parent dir, these are only times for now.
* hpfsnode have to be locked.
*/
int
hpfs_updateparent (
struct hpfsnode *hp)
{
struct hpfsnode *dhp;
struct vnode *dvp;
struct hpfsdirent *dep;
struct buf * bp;
int error;
dprintf(("hpfs_updateparent(0x%x): \n", hp->h_no));
if (!(hp->h_flag & H_PARCHANGE))
return (0);
if (!(hp->h_flag & H_PARVALID)) {
error = hpfs_validateparent (hp);
if (error)
return (error);
}
if (hp->h_no == hp->h_fn.fn_parent) {
dhp = hp;
} else {
error = VFS_VGET(hp->h_hpmp->hpm_mp, hp->h_fn.fn_parent,
LK_EXCLUSIVE, &dvp);
if (error)
return (error);
dhp = VTOHP(dvp);
}
error = hpfs_genlookupbyname (dhp, hp->h_name, hp->h_namelen,
&bp, &dep);
if (error) {
goto failed;
}
dep->de_atime = hp->h_atime;
dep->de_mtime = hp->h_mtime;
dep->de_size = hp->h_fn.fn_size;
bdwrite (bp);
hp->h_flag &= ~H_PARCHANGE;
error = 0;
failed:
if (hp != dhp)
vput(dvp);
return (0);
}
/*
* Write down on disk changes done to fnode. hpfsnode have to be locked.
*/
int
hpfs_update (
struct hpfsnode *hp)
{
struct buf * bp;
dprintf(("hpfs_update(0x%x): \n", hp->h_no));
if (!(hp->h_flag & H_CHANGE))
return (0);
bp = getblk(hp->h_devvp, hp->h_no, FNODESIZE, 0, 0, 0);
clrbuf(bp);
bcopy (&hp->h_fn, bp->b_data, sizeof(struct fnode));
bdwrite (bp);
hp->h_flag &= ~H_CHANGE;
if (hp->h_flag & H_PARCHANGE)
return (hpfs_updateparent(hp));
return (0);
}
/*
* Truncate file to specifed size. hpfsnode have to be locked.
*/
int
hpfs_truncate (
struct hpfsnode *hp,
u_long size)
{
struct hpfsmount *hpmp = hp->h_hpmp;
lsn_t newblen, oldblen;
int error, pf;
dprintf(("hpfs_truncate(0x%x, 0x%x -> 0x%lx): ",
hp->h_no, hp->h_fn.fn_size, size));
newblen = (size + DEV_BSIZE - 1) >> DEV_BSHIFT;
oldblen = (hp->h_fn.fn_size + DEV_BSIZE - 1) >> DEV_BSHIFT;
dprintf(("blen: 0x%x -> 0x%x\n", oldblen, newblen));
error = hpfs_truncatealblk (hpmp, &hp->h_fn.fn_ab, newblen, &pf);
if (error)
return (error);
if (pf) {
hp->h_fn.fn_ab.ab_flag = 0;
hp->h_fn.fn_ab.ab_freecnt = 0x8;
hp->h_fn.fn_ab.ab_busycnt = 0x0;
hp->h_fn.fn_ab.ab_freeoff = sizeof(alblk_t);
}
hp->h_fn.fn_size = size;
hp->h_flag |= (H_CHANGE | H_PARCHANGE);
dprintf(("hpfs_truncate: successful\n"));
return (0);
}
/*
* Enlarge file to specifed size. hpfsnode have to be locked.
*/
int
hpfs_extend (
struct hpfsnode *hp,
u_long size)
{
struct hpfsmount *hpmp = hp->h_hpmp;
lsn_t newblen, oldblen;
int error;
dprintf(("hpfs_extend(0x%x, 0x%x -> 0x%lx): ",
hp->h_no, hp->h_fn.fn_size, size));
if (hpmp->hpm_bavail < 0x10)
return (ENOSPC);
newblen = (size + DEV_BSIZE - 1) >> DEV_BSHIFT;
oldblen = (hp->h_fn.fn_size + DEV_BSIZE - 1) >> DEV_BSHIFT;
dprintf(("blen: 0x%x -> 0x%x\n", oldblen, newblen));
error = hpfs_addextent(hpmp, hp, newblen - oldblen);
if (error) {
printf("hpfs_extend: FAILED TO ADD EXTENT %d\n", error);
return (error);
}
hp->h_fn.fn_size = size;
hp->h_flag |= (H_CHANGE | H_PARCHANGE);
dprintf(("hpfs_extend: successful\n"));
return (0);
}
/*
* Read AlSec structure, and check if magic is valid.
* You don't need to brelse buf on error.
*/
int
hpfs_breadstruct (
struct hpfsmount *hpmp,
lsn_t lsn,
u_int len,
u_int32_t magic,
struct buf **bpp)
{
struct buf *bp;
u_int32_t *mp;
int error;
dprintf(("hpfs_breadstruct: reading at 0x%x\n", lsn));
*bpp = NULL;
error = bread(hpmp->hpm_devvp, lsn, len, NOCRED, &bp);
if (error) {
brelse(bp);
return (error);
}
mp = (u_int32_t *) bp->b_data;
if (*mp != magic) {
brelse(bp);
printf("hpfs_breadstruct: MAGIC DOESN'T MATCH (0x%08x != 0x%08x)\n",
*mp, magic);
return (EINVAL);
}
*bpp = bp;
return (0);
}

View File

@ -1,89 +0,0 @@
/*-
* Copyright (c) 1998, 1999 Semen Ustimenko (semenu@FreeBSD.org)
* 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.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
*
* $FreeBSD$
*/
#define hpfs_bmmarkfree(hpmp, bn,bl) hpfs_bmmark(hpmp, bn, bl, 1)
#define hpfs_bmmarkbusy(hpmp, bn,bl) hpfs_bmmark(hpmp, bn, bl, 0)
u_long hpfs_checksum (u_int8_t *, int);
int hpfs_bminit (struct hpfsmount *);
void hpfs_bmdeinit (struct hpfsmount *);
int hpfs_bmfblookup (struct hpfsmount *, lsn_t *);
int hpfs_bmmark (struct hpfsmount *, lsn_t, u_long, int);
int hpfs_bmlookup (struct hpfsmount *, u_long, lsn_t, u_long,
lsn_t *, u_long *);
struct hpfs_args;
int hpfs_cpinit (struct mount *, struct hpfsmount *);
int hpfs_cpdeinit (struct hpfsmount *);
int hpfs_cpload (struct hpfsmount *, struct cpiblk *,
struct cpdblk *);
int hpfs_cpstrnnicmp (struct hpfsmount *, char *, int, u_int16_t,
char *, int, u_int16_t);
int hpfs_cmpfname (struct hpfsmount *, char *, int,
char *, int, u_int16_t);
/* XXX Need unsigned conversion? */
#define hpfs_u2d(hpmp, c) ((((u_char)(c))&0x80)?(hpmp->hpm_u2d[((u_char)(c))&0x7F]):((u_char)(c)))
#define hpfs_d2u(hpmp, c) ((((u_char)(c))&0x80)?(hpmp->hpm_d2u[((u_char)(c))&0x7F]):((u_char)(c)))
#define hpfs_toupper(hpmp, c, cp) ((((u_char)(c))&0x80) ? ((u_char)((hpmp)->hpm_cpdblk[(cp)].b_upcase[((u_char)(c))&0x7F])) : ((((u_char)(c)) >= 'a' && ((u_char)(c)) <='z')?(((u_char)(c))-'a'+'A'):((u_char)(c))))
int hpfs_truncate (struct hpfsnode *, u_long);
int hpfs_extend (struct hpfsnode *, u_long);
int hpfs_updateparent (struct hpfsnode *);
int hpfs_update (struct hpfsnode *);
int hpfs_validateparent (struct hpfsnode *);
struct timespec hpfstimetounix (u_long);
int hpfs_genlookupbyname (struct hpfsnode *, char *, int,
struct buf **, struct hpfsdirent **);
int hpfs_makefnode (struct vnode *, struct vnode **,
struct componentname *, struct vattr *);
int hpfs_removefnode (struct vnode *, struct vnode *,
struct componentname *);
int hpfs_breadstruct (struct hpfsmount *, lsn_t, u_int, u_int32_t,
struct buf **);
#define hpfs_breadalsec(hpmp, lsn, bpp) \
hpfs_breadstruct(hpmp, lsn, DEV_BSIZE, AS_MAGIC, bpp)
#define hpfs_breaddirblk(hpmp, lsn, bpp) \
hpfs_breadstruct(hpmp, lsn, D_BSIZE, D_MAGIC, bpp)
#if 0
#define hpfs_hplock(hp, p) \
lockmgr(&(hp)->h_intlock, LK_EXCLUSIVE, (p))
#define hpfs_hpunlock(hp, p) \
lockmgr(&(hp)->h_intlock, LK_RELEASE, (p))
#endif
int hpfs_hpbmap (struct hpfsnode *, daddr_t, daddr_t *, int *);
int hpfs_truncatealblk (struct hpfsmount *, alblk_t *, lsn_t,int *);
int hpfs_addextent (struct hpfsmount *, struct hpfsnode *, u_long);

View File

@ -1,545 +0,0 @@
/*-
* Copyright (c) 1998, 1999 Semen Ustimenko (semenu@FreeBSD.org)
* 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.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
*
* $FreeBSD$
*/
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/namei.h>
#include <sys/conf.h>
#include <sys/proc.h>
#include <sys/kernel.h>
#include <sys/vnode.h>
#include <sys/mount.h>
#include <sys/bio.h>
#include <sys/buf.h>
#include <sys/fcntl.h>
#include <sys/malloc.h>
#include <geom/geom.h>
#include <geom/geom_vfs.h>
#include <vm/vm.h>
#include <vm/vm_param.h>
#include <vm/vm_page.h>
#include <vm/vm_object.h>
#include <vm/vm_extern.h>
#include <fs/hpfs/hpfs.h>
#include <fs/hpfs/hpfsmount.h>
#include <fs/hpfs/hpfs_subr.h>
MALLOC_DEFINE(M_HPFSMNT, "hpfs_mount", "HPFS mount structure");
MALLOC_DEFINE(M_HPFSNO, "hpfs_node", "HPFS node structure");
struct sockaddr;
static int hpfs_mountfs(register struct vnode *, struct mount *,
struct thread *);
static vfs_fhtovp_t hpfs_fhtovp;
static vfs_vget_t hpfs_vget;
static vfs_cmount_t hpfs_cmount;
static vfs_mount_t hpfs_mount;
static vfs_root_t hpfs_root;
static vfs_statfs_t hpfs_statfs;
static vfs_unmount_t hpfs_unmount;
static int
hpfs_cmount (
struct mntarg *ma,
void *data,
uint64_t flags)
{
struct hpfs_args args;
struct export_args exp;
int error;
error = copyin(data, (caddr_t)&args, sizeof (struct hpfs_args));
if (error)
return (error);
vfs_oexport_conv(&args.export, &exp);
ma = mount_argsu(ma, "from", args.fspec, MAXPATHLEN);
ma = mount_arg(ma, "export", &exp, sizeof(exp));
ma = mount_argf(ma, "uid", "%d", args.uid);
ma = mount_argf(ma, "gid", "%d", args.gid);
ma = mount_argf(ma, "mode", "%d", args.mode);
if (args.flags & HPFSMNT_TABLES) {
ma = mount_arg(ma, "d2u", args.d2u, sizeof args.d2u);
ma = mount_arg(ma, "u2d", args.u2d, sizeof args.u2d);
}
error = kernel_mount(ma, flags);
return (error);
}
static const char *hpfs_opts[] = {
"from", "export", "uid", "gid", "mode", "d2u", "u2d", NULL
};
static int
hpfs_mount (struct mount *mp)
{
int err = 0, error;
struct vnode *devvp;
struct thread *td;
struct nameidata ndp;
struct export_args export;
char *from;
td = curthread;
dprintf(("hpfs_omount():\n"));
/*
***
* Mounting non-root filesystem or updating a filesystem
***
*/
if (vfs_filteropt(mp->mnt_optnew, hpfs_opts))
return (EINVAL);
from = vfs_getopts(mp->mnt_optnew, "from", &error);
if (error)
return (error);
/*
* If updating, check whether changing from read-only to
* read/write; if there is no device name, that's all we do.
*/
if (mp->mnt_flag & MNT_UPDATE) {
dprintf(("hpfs_omount: MNT_UPDATE: "));
if (from == NULL) {
error = vfs_copyopt(mp->mnt_optnew, "export",
&export, sizeof export);
if (error)
return (error);
dprintf(("export 0x%x\n",args.export.ex_flags));
err = vfs_export(mp, &export);
if (err) {
printf("hpfs_omount: vfs_export failed %d\n",
err);
}
goto success;
} else {
dprintf(("name [FAILED]\n"));
err = EINVAL;
goto success;
}
dprintf(("\n"));
}
/*
* Not an update, or updating the name: look up the name
* and verify that it refers to a sensible block device.
*/
NDINIT(&ndp, LOOKUP, FOLLOW | LOCKLEAF, UIO_SYSSPACE, from, td);
err = namei(&ndp);
if (err) {
/* can't get devvp!*/
goto error_1;
}
devvp = ndp.ni_vp;
if (!vn_isdisk(devvp, &err)) {
vput(devvp);
return (err);
}
/*
********************
* NEW MOUNT
********************
*/
/*
* Since this is a new mount, we want the names for
* the device and the mount point copied in. If an
* error occurs, the mountpoint is discarded by the
* upper level code. Note that vfs_omount() handles
* copying the mountpoint f_mntonname for us, so we
* don't have to do it here unless we want to set it
* to something other than "path" for some rason.
*/
/* Save "mounted from" info for mount point (NULL pad)*/
vfs_mountedfrom(mp, from);
err = hpfs_mountfs(devvp, mp, td);
if (err) {
vrele(devvp);
goto error_1;
}
goto success;
error_1: /* no state to back out*/
/* XXX: Missing NDFREE(&ndp, ...) */
success:
return( err);
}
/*
* Common code for mount and mountroot
*/
int
hpfs_mountfs(devvp, mp, td)
register struct vnode *devvp;
struct mount *mp;
struct thread *td;
{
int error, ronly, v;
struct sublock *sup;
struct spblock *spp;
struct hpfsmount *hpmp;
struct buf *bp = NULL;
struct vnode *vp;
struct cdev *dev = devvp->v_rdev;
struct g_consumer *cp;
struct bufobj *bo;
if (mp->mnt_flag & MNT_ROOTFS)
return (EOPNOTSUPP);
dprintf(("hpfs_mountfs():\n"));
ronly = (mp->mnt_flag & MNT_RDONLY) != 0;
/* XXX: use VOP_ACCESS to check FS perms */
DROP_GIANT();
g_topology_lock();
error = g_vfs_open(devvp, &cp, "hpfs", ronly ? 0 : 1);
g_topology_unlock();
PICKUP_GIANT();
VOP_UNLOCK(devvp, 0);
if (error)
return (error);
bo = &devvp->v_bufobj;
bo->bo_private = cp;
bo->bo_ops = g_vfs_bufops;
/*
* Do actual mount
*/
hpmp = malloc(sizeof(struct hpfsmount), M_HPFSMNT, M_WAITOK | M_ZERO);
hpmp->hpm_cp = cp;
hpmp->hpm_bo = bo;
/* Read in SuperBlock */
error = bread(devvp, SUBLOCK, SUSIZE, NOCRED, &bp);
if (error)
goto failed;
bcopy(bp->b_data, &hpmp->hpm_su, sizeof(struct sublock));
brelse(bp); bp = NULL;
/* Read in SpareBlock */
error = bread(devvp, SPBLOCK, SPSIZE, NOCRED, &bp);
if (error)
goto failed;
bcopy(bp->b_data, &hpmp->hpm_sp, sizeof(struct spblock));
brelse(bp); bp = NULL;
sup = &hpmp->hpm_su;
spp = &hpmp->hpm_sp;
/* Check magic */
if (sup->su_magic != SU_MAGIC) {
printf("hpfs_mountfs: SuperBlock MAGIC DOESN'T MATCH\n");
error = EINVAL;
goto failed;
}
if (spp->sp_magic != SP_MAGIC) {
printf("hpfs_mountfs: SpareBlock MAGIC DOESN'T MATCH\n");
error = EINVAL;
goto failed;
}
mp->mnt_data = hpmp;
hpmp->hpm_devvp = devvp;
hpmp->hpm_dev = devvp->v_rdev;
hpmp->hpm_mp = mp;
if (vfs_scanopt(mp->mnt_optnew, "uid", "%d", &v) == 1)
hpmp->hpm_uid = v;
if (vfs_scanopt(mp->mnt_optnew, "gid", "%d", &v) == 1)
hpmp->hpm_gid = v;
if (vfs_scanopt(mp->mnt_optnew, "mode", "%d", &v) == 1)
hpmp->hpm_mode = v;
error = hpfs_bminit(hpmp);
if (error)
goto failed;
error = hpfs_cpinit(mp, hpmp);
if (error) {
hpfs_bmdeinit(hpmp);
goto failed;
}
error = hpfs_root(mp, LK_EXCLUSIVE, &vp);
if (error) {
hpfs_cpdeinit(hpmp);
hpfs_bmdeinit(hpmp);
goto failed;
}
vput(vp);
mp->mnt_stat.f_fsid.val[0] = (long)dev2udev(dev);
mp->mnt_stat.f_fsid.val[1] = mp->mnt_vfc->vfc_typenum;
mp->mnt_maxsymlinklen = 0;
MNT_ILOCK(mp);
mp->mnt_flag |= MNT_LOCAL;
MNT_IUNLOCK(mp);
return (0);
failed:
if (bp)
brelse (bp);
mp->mnt_data = NULL;
DROP_GIANT();
g_topology_lock();
g_vfs_close(cp);
g_topology_unlock();
PICKUP_GIANT();
return (error);
}
static int
hpfs_unmount(
struct mount *mp,
int mntflags)
{
int error, flags;
register struct hpfsmount *hpmp = VFSTOHPFS(mp);
dprintf(("hpfs_unmount():\n"));
flags = 0;
if(mntflags & MNT_FORCE)
flags |= FORCECLOSE;
dprintf(("hpfs_unmount: vflushing...\n"));
error = vflush(mp, 0, flags, curthread);
if (error) {
printf("hpfs_unmount: vflush failed: %d\n",error);
return (error);
}
vinvalbuf(hpmp->hpm_devvp, V_SAVE, 0, 0);
DROP_GIANT();
g_topology_lock();
g_vfs_close(hpmp->hpm_cp);
g_topology_unlock();
PICKUP_GIANT();
vrele(hpmp->hpm_devvp);
dprintf(("hpfs_umount: freeing memory...\n"));
hpfs_cpdeinit(hpmp);
hpfs_bmdeinit(hpmp);
mp->mnt_data = NULL;
MNT_ILOCK(mp);
mp->mnt_flag &= ~MNT_LOCAL;
MNT_IUNLOCK(mp);
free(hpmp, M_HPFSMNT);
return (0);
}
static int
hpfs_root(
struct mount *mp,
int flags,
struct vnode **vpp)
{
int error = 0;
struct hpfsmount *hpmp = VFSTOHPFS(mp);
dprintf(("hpfs_root():\n"));
error = VFS_VGET(mp, (ino_t)hpmp->hpm_su.su_rootfno, LK_EXCLUSIVE, vpp);
if(error) {
printf("hpfs_root: VFS_VGET failed: %d\n",error);
return (error);
}
return (error);
}
static int
hpfs_statfs(
struct mount *mp,
struct statfs *sbp)
{
struct hpfsmount *hpmp = VFSTOHPFS(mp);
dprintf(("hpfs_statfs(): HPFS%d.%d\n",
hpmp->hpm_su.su_hpfsver, hpmp->hpm_su.su_fnctver));
sbp->f_type = mp->mnt_vfc->vfc_typenum;
sbp->f_bsize = DEV_BSIZE;
sbp->f_iosize = DEV_BSIZE;
sbp->f_blocks = hpmp->hpm_su.su_btotal;
sbp->f_bfree = sbp->f_bavail = hpmp->hpm_bavail;
sbp->f_ffree = 0;
sbp->f_files = 0;
sbp->f_flags = mp->mnt_flag;
return (0);
}
/*ARGSUSED*/
static int
hpfs_fhtovp(
struct mount *mp,
struct fid *fhp,
int flags,
struct vnode **vpp)
{
struct vnode *nvp;
struct hpfid *hpfhp = (struct hpfid *)fhp;
int error;
if ((error = VFS_VGET(mp, hpfhp->hpfid_ino, LK_EXCLUSIVE, &nvp)) != 0) {
*vpp = NULLVP;
return (error);
}
/* XXX as unlink/rmdir/mkdir/creat are not currently possible
* with HPFS, we don't need to check anything else for now */
*vpp = nvp;
return (0);
}
static int
hpfs_vget(
struct mount *mp,
ino_t ino,
int flags,
struct vnode **vpp)
{
struct hpfsmount *hpmp = VFSTOHPFS(mp);
struct vnode *vp;
struct hpfsnode *hp;
struct buf *bp;
int error;
dprintf(("hpfs_vget(0x%x): ",ino));
error = vfs_hash_get(mp, ino, flags, curthread, vpp, NULL, NULL);
if (error || *vpp != NULL)
return (error);
*vpp = NULL;
hp = NULL;
vp = NULL;
/*
* We have to lock node creation for a while,
* but then we have to call getnewvnode(),
* this may cause hpfs_reclaim() to be called,
* this may need to VOP_VGET() parent dir for
* update reasons, and if parent is not in
* hash, we have to lock node creation...
* To solve this, we MALLOC, getnewvnode and init while
* not locked (probability of node appearence
* at that time is little, and anyway - we'll
* check for it).
*/
hp = malloc(sizeof(struct hpfsnode),
M_HPFSNO, M_WAITOK);
error = getnewvnode("hpfs", mp, &hpfs_vnodeops, &vp);
if (error) {
printf("hpfs_vget: can't get new vnode\n");
free(hp, M_HPFSNO);
return (error);
}
dprintf(("prenew "));
vp->v_data = hp;
if (ino == (ino_t)hpmp->hpm_su.su_rootfno)
vp->v_vflag |= VV_ROOT;
mtx_init(&hp->h_interlock, "hpfsnode interlock", NULL, MTX_DEF);
hp->h_flag = H_INVAL;
hp->h_vp = vp;
hp->h_hpmp = hpmp;
hp->h_no = ino;
hp->h_dev = hpmp->hpm_dev;
hp->h_uid = hpmp->hpm_uid;
hp->h_gid = hpmp->hpm_uid;
hp->h_mode = hpmp->hpm_mode;
hp->h_devvp = hpmp->hpm_devvp;
lockmgr(vp->v_vnlock, LK_EXCLUSIVE, NULL);
error = insmntque(vp, mp);
if (error != 0) {
free(hp, M_HPFSNO);
return (error);
}
error = vfs_hash_insert(vp, ino, flags, curthread, vpp, NULL, NULL);
if (error || *vpp != NULL)
return (error);
error = bread(hpmp->hpm_devvp, ino, FNODESIZE, NOCRED, &bp);
if (error) {
printf("hpfs_vget: can't read ino %ju\n", (uintmax_t)ino);
vput(vp);
return (error);
}
bcopy(bp->b_data, &hp->h_fn, sizeof(struct fnode));
brelse(bp);
if (hp->h_fn.fn_magic != FN_MAGIC) {
printf("hpfs_vget: MAGIC DOESN'T MATCH\n");
vput(vp);
return (EINVAL);
}
vp->v_type = hp->h_fn.fn_flag ? VDIR:VREG;
hp->h_flag &= ~H_INVAL;
*vpp = vp;
return (0);
}
static struct vfsops hpfs_vfsops = {
.vfs_fhtovp = hpfs_fhtovp,
.vfs_cmount = hpfs_cmount,
.vfs_mount = hpfs_mount,
.vfs_root = hpfs_root,
.vfs_statfs = hpfs_statfs,
.vfs_unmount = hpfs_unmount,
.vfs_vget = hpfs_vget,
};
VFS_SET(hpfs_vfsops, hpfs, 0);

File diff suppressed because it is too large Load Diff

View File

@ -1,39 +0,0 @@
/*-
* Copyright (c) 1998, 1999 Semen Ustimenko (semenu@FreeBSD.org)
* 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.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
*
* $FreeBSD$
*/
#define HPFSMNT_TABLES 0x0001
struct hpfs_args {
char *fspec; /* block special device to mount */
struct oexport_args export; /* network export information */
uid_t uid; /* uid that owns hpfs files */
gid_t gid; /* gid that owns hpfs files */
mode_t mode; /* mask to be applied for hpfs perms */
u_long flags; /* additional flags */
u_char d2u[0x80];
u_char u2d[0x80];
};

View File

@ -1,308 +0,0 @@
/* $NetBSD: ntfs.h,v 1.9 1999/10/31 19:45:26 jdolecek Exp $ */
/*-
* Copyright (c) 1998, 1999 Semen Ustimenko
* 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.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
*
* $FreeBSD$
*/
/*#define NTFS_DEBUG 1*/
typedef uint64_t cn_t;
typedef uint16_t wchar;
#pragma pack(1)
#define BBSIZE 1024
#define BBOFF ((off_t)(0))
#define BBLOCK 0
#define NTFS_MFTINO 0
#define NTFS_VOLUMEINO 3
#define NTFS_ATTRDEFINO 4
#define NTFS_ROOTINO 5
#define NTFS_BITMAPINO 6
#define NTFS_BOOTINO 7
#define NTFS_BADCLUSINO 8
#define NTFS_UPCASEINO 10
#define NTFS_MAXFILENAME 255
struct fixuphdr {
uint32_t fh_magic;
uint16_t fh_foff;
uint16_t fh_fnum;
};
#define NTFS_AF_INRUN 0x00000001
struct attrhdr {
uint32_t a_type;
uint32_t reclen;
uint8_t a_flag;
uint8_t a_namelen;
uint8_t a_nameoff;
uint8_t reserved1;
uint8_t a_compression;
uint8_t reserved2;
uint16_t a_index;
};
#define NTFS_A_STD 0x10
#define NTFS_A_ATTRLIST 0x20
#define NTFS_A_NAME 0x30
#define NTFS_A_VOLUMENAME 0x60
#define NTFS_A_DATA 0x80
#define NTFS_A_INDXROOT 0x90
#define NTFS_A_INDX 0xA0
#define NTFS_A_INDXBITMAP 0xB0
#define NTFS_MAXATTRNAME 255
struct attr {
struct attrhdr a_hdr;
union {
struct {
uint16_t a_datalen;
uint16_t reserved1;
uint16_t a_dataoff;
uint16_t a_indexed;
} a_S_r;
struct {
cn_t a_vcnstart;
cn_t a_vcnend;
uint16_t a_dataoff;
uint16_t a_compressalg;
uint32_t reserved1;
uint64_t a_allocated;
uint64_t a_datalen;
uint64_t a_initialized;
} a_S_nr;
} a_S;
};
#define a_r a_S.a_S_r
#define a_nr a_S.a_S_nr
typedef struct {
uint64_t t_create;
uint64_t t_write;
uint64_t t_mftwrite;
uint64_t t_access;
} ntfs_times_t;
#define NTFS_FFLAG_RDONLY 0x01LL
#define NTFS_FFLAG_HIDDEN 0x02LL
#define NTFS_FFLAG_SYSTEM 0x04LL
#define NTFS_FFLAG_ARCHIVE 0x20LL
#define NTFS_FFLAG_COMPRESSED 0x0800LL
#define NTFS_FFLAG_DIR 0x10000000LL
struct attr_name {
uint32_t n_pnumber; /* Parent ntnode */
uint32_t reserved;
ntfs_times_t n_times;
uint64_t n_size;
uint64_t n_attrsz;
uint64_t n_flag;
uint8_t n_namelen;
uint8_t n_nametype;
uint16_t n_name[1];
};
#define NTFS_IRFLAG_INDXALLOC 0x00000001
struct attr_indexroot {
uint32_t ir_unkn1; /* always 0x30 */
uint32_t ir_unkn2; /* always 0x1 */
uint32_t ir_size;/* ??? */
uint32_t ir_unkn3; /* number of cluster */
uint32_t ir_unkn4; /* always 0x10 */
uint32_t ir_datalen; /* sizeof simething */
uint32_t ir_allocated; /* same as above */
uint16_t ir_flag;/* ?? always 1 */
uint16_t ir_unkn7;
};
struct attr_attrlist {
uint32_t al_type; /* Attribute type */
uint16_t reclen; /* length of this entry */
uint8_t al_namelen; /* Attribute name len */
uint8_t al_nameoff; /* Name offset from entry start */
uint64_t al_vcnstart; /* VCN number */
uint32_t al_inumber; /* Parent ntnode */
uint32_t reserved;
uint16_t al_index; /* Attribute index in MFT record */
uint16_t al_name[1]; /* Name */
};
#define NTFS_INDXMAGIC (uint32_t)(0x58444E49)
struct attr_indexalloc {
struct fixuphdr ia_fixup;
uint64_t unknown1;
cn_t ia_bufcn;
uint16_t ia_hdrsize;
uint16_t unknown2;
uint32_t ia_inuse;
uint32_t ia_allocated;
};
#define NTFS_IEFLAG_SUBNODE 0x00000001
#define NTFS_IEFLAG_LAST 0x00000002
struct attr_indexentry {
uint32_t ie_number;
uint32_t unknown1;
uint16_t reclen;
uint16_t ie_size;
uint32_t ie_flag; /* 1 - has subnodes, 2 - last */
uint32_t ie_fpnumber;
uint32_t unknown2;
ntfs_times_t ie_ftimes;
uint64_t ie_fallocated;
uint64_t ie_fsize;
uint64_t ie_fflag;
uint8_t ie_fnamelen;
uint8_t ie_fnametype;
wchar ie_fname[NTFS_MAXFILENAME];
/* cn_t ie_bufcn; buffer with subnodes */
};
#define NTFS_FILEMAGIC (uint32_t)(0x454C4946)
#define NTFS_BLOCK_SIZE 512
#define NTFS_FRFLAG_DIR 0x0002
struct filerec {
struct fixuphdr fr_fixup;
uint8_t reserved[8];
uint16_t fr_seqnum; /* Sequence number */
uint16_t fr_nlink;
uint16_t fr_attroff; /* offset to attributes */
uint16_t fr_flags; /* 1-nonresident attr, 2-directory */
uint32_t fr_size;/* hdr + attributes */
uint32_t fr_allocated; /* allocated length of record */
uint64_t fr_mainrec; /* main record */
uint16_t fr_attrnum; /* maximum attr number + 1 ??? */
};
#define NTFS_ATTRNAME_MAXLEN 0x40
#define NTFS_ADFLAG_NONRES 0x0080 /* Attrib can be non resident */
#define NTFS_ADFLAG_INDEX 0x0002 /* Attrib can be indexed */
struct attrdef {
wchar ad_name[NTFS_ATTRNAME_MAXLEN];
uint32_t ad_type;
uint32_t reserved1[2];
uint32_t ad_flag;
uint64_t ad_minlen;
uint64_t ad_maxlen; /* -1 for nonlimited */
};
struct ntvattrdef {
char ad_name[0x40];
int ad_namelen;
uint32_t ad_type;
};
#define NTFS_BBID "NTFS "
#define NTFS_BBIDLEN 8
struct bootfile {
uint8_t reserved1[3]; /* asm jmp near ... */
uint8_t bf_sysid[8]; /* 'NTFS ' */
uint16_t bf_bps; /* bytes per sector */
uint8_t bf_spc; /* sectors per cluster */
uint8_t reserved2[7]; /* unused (zeroed) */
uint8_t bf_media; /* media desc. (0xF8) */
uint8_t reserved3[2];
uint16_t bf_spt; /* sectors per track */
uint16_t bf_heads; /* number of heads */
uint8_t reserver4[12];
uint64_t bf_spv; /* sectors per volume */
cn_t bf_mftcn; /* $MFT cluster number */
cn_t bf_mftmirrcn; /* $MFTMirr cn */
uint8_t bf_mftrecsz; /* MFT record size (clust) */
/* 0xF6 inducates 1/4 */
uint32_t bf_ibsz; /* index buffer size */
uint32_t bf_volsn; /* volume ser. num. */
};
#define NTFS_SYSNODESNUM 0x0B
struct ntfsmount {
struct mount *ntm_mountp; /* filesystem vfs structure */
struct bootfile ntm_bootfile;
struct g_consumer *ntm_cp;
struct bufobj *ntm_bo;
struct vnode *ntm_devvp; /* block device mounted vnode */
struct vnode *ntm_sysvn[NTFS_SYSNODESNUM];
uint32_t ntm_bpmftrec;
uid_t ntm_uid;
gid_t ntm_gid;
mode_t ntm_mode;
uint64_t ntm_flag;
cn_t ntm_cfree;
struct ntvattrdef *ntm_ad;
int ntm_adnum;
wchar * ntm_82u; /* 8bit to Unicode */
char ** ntm_u28; /* Unicode to 8 bit */
void * ntm_ic_l2u; /* Local to Unicode (iconv) */
void * ntm_ic_u2l; /* Unicode to Local (iconv) */
uint8_t ntm_multiplier; /* NTFS blockno to DEV_BSIZE sectorno */
};
#define ntm_mftcn ntm_bootfile.bf_mftcn
#define ntm_mftmirrcn ntm_bootfile.bf_mftmirrcn
#define ntm_mftrecsz ntm_bootfile.bf_mftrecsz
#define ntm_spc ntm_bootfile.bf_spc
#define ntm_bps ntm_bootfile.bf_bps
#pragma pack()
#define NTFS_NEXTREC(s, type) ((type)(((caddr_t) s) + (s)->reclen))
/* Convert mount ptr to ntfsmount ptr. */
#define VFSTONTFS(mp) ((struct ntfsmount *)((mp)->mnt_data))
#define VTONT(v) FTONT(VTOF(v))
#define VTOF(v) ((struct fnode *)((v)->v_data))
#define FTOV(f) ((f)->f_vp)
#define FTONT(f) ((f)->f_ip)
#define ntfs_cntobn(cn) (daddr_t)((cn) * (ntmp->ntm_spc))
#define ntfs_cntob(cn) (off_t)((cn) * (ntmp)->ntm_spc * (ntmp)->ntm_bps)
#define ntfs_btocn(off) (cn_t)((off) / ((ntmp)->ntm_spc * (ntmp)->ntm_bps))
#define ntfs_btocl(off) (cn_t)((off + ntfs_cntob(1) - 1) / ((ntmp)->ntm_spc * (ntmp)->ntm_bps))
#define ntfs_btocnoff(off) (off_t)((off) % ((ntmp)->ntm_spc * (ntmp)->ntm_bps))
#define ntfs_bntob(bn) (daddr_t)((bn) * (ntmp)->ntm_bps)
#define ntfs_bpbl (daddr_t)((ntmp)->ntm_bps)
#ifdef MALLOC_DECLARE
MALLOC_DECLARE(M_NTFSNTNODE);
MALLOC_DECLARE(M_NTFSFNODE);
MALLOC_DECLARE(M_NTFSDIR);
MALLOC_DECLARE(M_NTFSNTHASH);
#endif
#if defined(NTFS_DEBUG)
#define dprintf(a) printf a
#if NTFS_DEBUG > 1
#define ddprintf(a) printf a
#else
#define ddprintf(a) (void)0
#endif
#else
#define dprintf(a) (void)0
#define ddprintf(a) (void)0
#endif
extern struct vop_vector ntfs_vnodeops;

View File

@ -1,111 +0,0 @@
/* $NetBSD: ntfs_compr.c,v 1.3 1999/07/26 14:02:31 jdolecek Exp $ */
/*-
* Copyright (c) 1998, 1999 Semen Ustimenko
* 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.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
*
* $FreeBSD$
*/
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/namei.h>
#include <sys/vnode.h>
#include <sys/mount.h>
#include <sys/file.h>
#include <fs/ntfs/ntfs.h>
#include <fs/ntfs/ntfs_compr.h>
#define GET_UINT16(addr) (*((u_int16_t *)(addr)))
int
ntfs_uncompblock(
u_int8_t * dbuf,
u_int8_t * cbuf)
{
u_int32_t ctag;
int len, dshift, lmask;
int blen, boff;
int i, j;
int pos, cpos;
len = GET_UINT16(cbuf) & 0xFFF;
dprintf(("ntfs_uncompblock: block length: %d + 3, 0x%x,0x%04x\n",
len, len, GET_UINT16(cbuf)));
if (!(GET_UINT16(cbuf) & 0x8000)) {
if ((len + 1) != NTFS_COMPBLOCK_SIZE) {
dprintf(("ntfs_uncompblock: len: %x instead of %d\n",
len, 0xfff));
}
memcpy(dbuf, cbuf + 2, len + 1);
memset(dbuf + len + 1, 0, NTFS_COMPBLOCK_SIZE - 1 - len);
return len + 3;
}
cpos = 2;
pos = 0;
while ((cpos < len + 3) && (pos < NTFS_COMPBLOCK_SIZE)) {
ctag = cbuf[cpos++];
for (i = 0; (i < 8) && (pos < NTFS_COMPBLOCK_SIZE); i++) {
if (ctag & 1) {
for (j = pos - 1, lmask = 0xFFF, dshift = 12;
j >= 0x10; j >>= 1) {
dshift--;
lmask >>= 1;
}
boff = -1 - (GET_UINT16(cbuf + cpos) >> dshift);
blen = 3 + (GET_UINT16(cbuf + cpos) & lmask);
for (j = 0; (j < blen) && (pos < NTFS_COMPBLOCK_SIZE); j++) {
dbuf[pos] = dbuf[pos + boff];
pos++;
}
cpos += 2;
} else {
dbuf[pos++] = cbuf[cpos++];
}
ctag >>= 1;
}
}
return len + 3;
}
int
ntfs_uncompunit(
struct ntfsmount * ntmp,
u_int8_t * uup,
u_int8_t * cup)
{
int i;
int off = 0;
int new;
for (i = 0; i * NTFS_COMPBLOCK_SIZE < ntfs_cntob(NTFS_COMPUNIT_CL); i++) {
new = ntfs_uncompblock(uup + i * NTFS_COMPBLOCK_SIZE, cup + off);
if (new == 0)
return (EINVAL);
off += new;
}
return (0);
}

View File

@ -1,35 +0,0 @@
/* $NetBSD: ntfs_compr.h,v 1.3 1999/07/26 14:02:31 jdolecek Exp $ */
/*-
* Copyright (c) 1998, 1999 Semen Ustimenko
* 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.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
*
* $FreeBSD$
*/
#define NTFS_COMPBLOCK_SIZE 0x1000
#define NTFS_COMPUNIT_CL 16
int ntfs_uncompblock(u_int8_t *, u_int8_t *);
int ntfs_uncompunit(struct ntfsmount *, u_int8_t *, u_int8_t *);

View File

@ -1,36 +0,0 @@
/*-
* Copyright (c) 2003 Ryuichiro Imura
* 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.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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 <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/kernel.h>
#include <sys/module.h>
#include <sys/mount.h>
#include <sys/iconv.h>
VFS_DECLARE_ICONV(ntfs);

View File

@ -1,130 +0,0 @@
/* $NetBSD: ntfs_ihash.c,v 1.5 1999/09/30 16:56:40 jdolecek Exp $ */
/*-
* Copyright (c) 1982, 1986, 1989, 1991, 1993, 1995
* The Regents of the University of California. 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.
* 4. Neither the name of the University 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 REGENTS 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 REGENTS 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.
*
* @(#)ufs_ihash.c 8.7 (Berkeley) 5/17/95
* $FreeBSD$
*/
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/lock.h>
#include <sys/vnode.h>
#include <sys/malloc.h>
#include <sys/mount.h>
#include <sys/mutex.h>
#include <fs/ntfs/ntfs.h>
#include <fs/ntfs/ntfs_inode.h>
#include <fs/ntfs/ntfs_ihash.h>
MALLOC_DEFINE(M_NTFSNTHASH, "ntfs_nthash", "NTFS ntnode hash tables");
/*
* Structures associated with inode cacheing.
*/
static LIST_HEAD(nthashhead, ntnode) *ntfs_nthashtbl;
static u_long ntfs_nthash; /* size of hash table - 1 */
#define NTNOHASH(inum) (&ntfs_nthashtbl[(inum) & ntfs_nthash])
static struct mtx ntfs_nthash_mtx;
struct lock ntfs_hashlock;
/*
* Initialize inode hash table.
*/
void
ntfs_nthashinit()
{
lockinit(&ntfs_hashlock, PINOD, "ntfs_nthashlock", 0, 0);
ntfs_nthashtbl = hashinit(desiredvnodes, M_NTFSNTHASH, &ntfs_nthash);
mtx_init(&ntfs_nthash_mtx, "ntfs nthash", NULL, MTX_DEF);
}
/*
* Destroy inode hash table.
*/
void
ntfs_nthashdestroy(void)
{
hashdestroy(ntfs_nthashtbl, M_NTFSNTHASH, ntfs_nthash);
lockdestroy(&ntfs_hashlock);
mtx_destroy(&ntfs_nthash_mtx);
}
/*
* Use the device/inum pair to find the incore inode, and return a pointer
* to it. If it is in core, return it, even if it is locked.
*/
struct ntnode *
ntfs_nthashlookup(dev, inum)
struct cdev *dev;
ino_t inum;
{
struct ntnode *ip;
mtx_lock(&ntfs_nthash_mtx);
LIST_FOREACH(ip, NTNOHASH(inum), i_hash)
if (inum == ip->i_number && dev == ip->i_dev)
break;
mtx_unlock(&ntfs_nthash_mtx);
return (ip);
}
/*
* Insert the ntnode into the hash table.
*/
void
ntfs_nthashins(ip)
struct ntnode *ip;
{
struct nthashhead *ipp;
mtx_lock(&ntfs_nthash_mtx);
ipp = NTNOHASH(ip->i_number);
LIST_INSERT_HEAD(ipp, ip, i_hash);
ip->i_flag |= IN_HASHED;
mtx_unlock(&ntfs_nthash_mtx);
}
/*
* Remove the inode from the hash table.
*/
void
ntfs_nthashrem(ip)
struct ntnode *ip;
{
mtx_lock(&ntfs_nthash_mtx);
if (ip->i_flag & IN_HASHED) {
ip->i_flag &= ~IN_HASHED;
LIST_REMOVE(ip, i_hash);
}
mtx_unlock(&ntfs_nthash_mtx);
}

View File

@ -1,37 +0,0 @@
/* $NetBSD: ntfs_ihash.h,v 1.4 1999/09/30 16:56:40 jdolecek Exp $ */
/*-
* Copyright (c) 1998, 1999 Semen Ustimenko
* 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.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
*
* $FreeBSD$
*/
extern struct lock ntfs_hashlock;
void ntfs_nthashinit(void);
void ntfs_nthashdestroy(void);
struct ntnode *ntfs_nthashlookup(struct cdev *, ino_t);
struct ntnode *ntfs_nthashget(struct cdev *, ino_t);
void ntfs_nthashins(struct ntnode *);
void ntfs_nthashrem(register struct ntnode *);

View File

@ -1,101 +0,0 @@
/* $NetBSD: ntfs_inode.h,v 1.8 1999/10/31 19:45:26 jdolecek Exp $ */
/*-
* Copyright (c) 1998, 1999 Semen Ustimenko
* 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.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
*
* $FreeBSD$
*/
/* These flags are kept in i_flag. */
#define IN_ACCESS 0x0001 /* Access time update request. */
#define IN_CHANGE 0x0002 /* Inode change time update request. */
#define IN_UPDATE 0x0004 /* Modification time update request. */
#define IN_MODIFIED 0x0008 /* Inode has been modified. */
#define IN_RENAME 0x0010 /* Inode is being renamed. */
#define IN_SHLOCK 0x0020 /* File has shared lock. */
#define IN_EXLOCK 0x0040 /* File has exclusive lock. */
#define IN_LAZYMOD 0x0080 /* Modified, but don't write yet. */
#define IN_HASHED 0x0800 /* Inode is on hash list */
#define IN_LOADED 0x8000 /* ntvattrs loaded */
#define IN_PRELOADED 0x4000 /* loaded from directory entry */
struct ntnode {
struct vnode *i_devvp; /* vnode of blk dev we live on */
struct cdev *i_dev; /* Device associated with the inode. */
LIST_ENTRY(ntnode) i_hash;
struct ntnode *i_next;
struct ntnode **i_prev;
struct ntfsmount *i_mp;
ino_t i_number;
u_int32_t i_flag;
/* locking */
struct lock i_lock;
struct mtx i_interlock;
int i_usecount;
LIST_HEAD(,fnode) i_fnlist;
LIST_HEAD(,ntvattr) i_valist;
long i_nlink; /* MFR */
ino_t i_mainrec; /* MFR */
u_int32_t i_frflag; /* MFR */
};
#define FN_PRELOADED 0x0001
#define FN_VALID 0x0002
#define FN_AATTRNAME 0x0004 /* space allocated for f_attrname */
struct fnode {
LIST_ENTRY(fnode) f_fnlist;
struct vnode *f_vp; /* Associatied vnode */
struct ntnode *f_ip; /* Associated ntnode */
u_long f_flag;
ntfs_times_t f_times; /* $NAME/dirinfo */
ino_t f_pnumber; /* $NAME/dirinfo */
u_int32_t f_fflag; /* $NAME/dirinfo */
u_int64_t f_size; /* defattr/dirinfo: */
u_int64_t f_allocated; /* defattr/dirinfo */
u_int32_t f_attrtype;
char *f_attrname;
/* for ntreaddir */
u_int32_t f_lastdattr;
u_int32_t f_lastdblnum;
u_int32_t f_lastdoff;
u_int32_t f_lastdnum;
caddr_t f_dirblbuf;
u_int32_t f_dirblsz;
};
/* This overlays the fid structure (see <sys/mount.h>) */
struct ntfid {
u_int16_t ntfid_len; /* Length of structure. */
u_int16_t ntfid_pad; /* Force 32-bit alignment. */
ino_t ntfid_ino; /* File number (ino). */
int32_t ntfid_gen; /* Generation number. */
};

File diff suppressed because it is too large Load Diff

View File

@ -1,120 +0,0 @@
/* $NetBSD: ntfs_subr.h,v 1.8 1999/10/10 14:48:37 jdolecek Exp $ */
/*-
* Copyright (c) 1998, 1999 Semen Ustimenko
* 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.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
*
* $FreeBSD$
*/
#define VA_LOADED 0x0001
#define VA_PRELOADED 0x0002
struct ntvattr {
LIST_ENTRY(ntvattr) va_list;
u_int32_t va_vflag;
struct vnode *va_vp;
struct ntnode *va_ip;
u_int32_t va_flag;
u_int32_t va_type;
u_int8_t va_namelen;
char va_name[NTFS_MAXATTRNAME];
u_int32_t va_compression;
u_int32_t va_compressalg;
u_int64_t va_datalen;
u_int64_t va_allocated;
cn_t va_vcnstart;
cn_t va_vcnend;
u_int16_t va_index;
union {
struct {
cn_t * cn;
cn_t * cl;
u_long cnt;
} vrun;
caddr_t datap;
struct attr_name *name;
struct attr_indexroot *iroot;
struct attr_indexalloc *ialloc;
} va_d;
};
#define va_vruncn va_d.vrun.cn
#define va_vruncl va_d.vrun.cl
#define va_vruncnt va_d.vrun.cnt
#define va_datap va_d.datap
#define va_a_name va_d.name
#define va_a_iroot va_d.iroot
#define va_a_ialloc va_d.ialloc
struct componentname;
struct fnode;
struct uio;
int ntfs_procfixups( struct ntfsmount *, u_int32_t, caddr_t, size_t );
int ntfs_parserun( cn_t *, cn_t *, u_int8_t *, u_long, u_long *);
int ntfs_runtocn( cn_t *, struct ntfsmount *, u_int8_t *, u_long, cn_t);
int ntfs_readntvattr_plain( struct ntfsmount *, struct ntnode *, struct ntvattr *, off_t, size_t, void *,size_t *, struct uio *);
int ntfs_readattr_plain( struct ntfsmount *, struct ntnode *, u_int32_t, char *, off_t, size_t, void *,size_t *, struct uio *);
int ntfs_readattr( struct ntfsmount *, struct ntnode *, u_int32_t, char *, off_t, size_t, void *, struct uio *);
int ntfs_filesize( struct ntfsmount *, struct fnode *, u_int64_t *, u_int64_t *);
int ntfs_times( struct ntfsmount *, struct ntnode *, ntfs_times_t *);
struct timespec ntfs_nttimetounix( u_int64_t );
int ntfs_ntreaddir( struct ntfsmount *, struct fnode *, u_int32_t, struct attr_indexentry **);
int ntfs_runtovrun( cn_t **, cn_t **, u_long *, u_int8_t *);
int ntfs_attrtontvattr( struct ntfsmount *, struct ntvattr **, struct attr * );
void ntfs_freentvattr( struct ntvattr * );
int ntfs_loadntvattrs( struct ntfsmount *, struct vnode *, caddr_t, struct ntvattr **);
struct ntvattr * ntfs_findntvattr( struct ntfsmount *, struct ntnode *, u_int32_t, cn_t );
int ntfs_ntlookupfile(struct ntfsmount *, struct vnode *, struct componentname *, struct vnode **);
int ntfs_isnamepermitted(struct ntfsmount *, struct attr_indexentry * );
int ntfs_ntvattrrele(struct ntvattr * );
int ntfs_ntvattrget(struct ntfsmount *, struct ntnode *, u_int32_t, const char *, cn_t , struct ntvattr **);
int ntfs_ntlookup(struct ntfsmount *, ino_t, struct ntnode **);
int ntfs_ntget(struct ntnode *);
void ntfs_ntref(struct ntnode *);
void ntfs_ntrele(struct ntnode *);
void ntfs_ntput(struct ntnode *);
int ntfs_loadntnode( struct ntfsmount *, struct ntnode * );
void ntfs_toupper_init(void);
void ntfs_toupper_destroy(void);
int ntfs_toupper_use(struct mount *, struct ntfsmount *);
void ntfs_toupper_unuse(void);
int ntfs_fget(struct ntfsmount *, struct ntnode *, int, char *, struct fnode **);
void ntfs_frele(struct fnode *);
int ntfs_u28_init(struct ntfsmount *ntmp, wchar *u2w, char *cs_local, char *cs_ntfs);
int ntfs_u28_uninit(struct ntfsmount *ntmp);
int ntfs_82u_init(struct ntfsmount *ntmp, char *cs_local, char *cs_ntfs);
int ntfs_82u_uninit(struct ntfsmount *ntmp);
char * ntfs_u28(char *outbuf, struct ntfsmount *ntmp, wchar wc);
wchar ntfs_82u(struct ntfsmount *ntmp, const char *c, int *len);
#define NTFS_U28(ch) ntfs_u28(tmpbuf, ntmp, (ch))
#define NTFS_82U(ch, len) ntfs_82u(ntmp, (ch), len)
#define NTFS_UASTRCMP(ustr, ustrlen, astr, astrlen) \
ntfs_uastrcmp(ntmp, (ustr), (ustrlen), (astr), (astrlen))
#define NTFS_UASTRICMP(ustr, ustrlen, astr, astrlen) \
ntfs_uastricmp(ntmp, (ustr), (ustrlen), (astr), (astrlen))

View File

@ -1,780 +0,0 @@
/* $NetBSD: ntfs_vfsops.c,v 1.23 1999/11/15 19:38:14 jdolecek Exp $ */
/*-
* Copyright (c) 1998, 1999 Semen Ustimenko
* 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.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
*
* $FreeBSD$
*/
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/namei.h>
#include <sys/conf.h>
#include <sys/priv.h>
#include <sys/proc.h>
#include <sys/kernel.h>
#include <sys/vnode.h>
#include <sys/mount.h>
#include <sys/bio.h>
#include <sys/buf.h>
#include <sys/fcntl.h>
#include <sys/malloc.h>
#include <sys/stat.h>
#include <sys/systm.h>
#include <geom/geom.h>
#include <geom/geom_vfs.h>
#include <vm/vm.h>
#include <vm/vm_param.h>
#include <vm/vm_page.h>
#include <vm/vm_object.h>
#include <vm/vm_extern.h>
/*#define NTFS_DEBUG 1*/
#include <fs/ntfs/ntfs.h>
#include <fs/ntfs/ntfs_inode.h>
#include <fs/ntfs/ntfs_subr.h>
#include <fs/ntfs/ntfs_vfsops.h>
#include <fs/ntfs/ntfs_ihash.h>
#include <fs/ntfs/ntfsmount.h>
static MALLOC_DEFINE(M_NTFSMNT, "ntfs_mount", "NTFS mount structure");
MALLOC_DEFINE(M_NTFSNTNODE,"ntfs_ntnode", "NTFS ntnode information");
MALLOC_DEFINE(M_NTFSFNODE,"ntfs_fnode", "NTFS fnode information");
MALLOC_DEFINE(M_NTFSDIR,"ntfs_dir", "NTFS dir buffer");
static int ntfs_mountfs(register struct vnode *, struct mount *,
struct thread *);
static int ntfs_calccfree(struct ntfsmount *ntmp, cn_t *cfreep);
static vfs_init_t ntfs_init;
static vfs_uninit_t ntfs_uninit;
static vfs_vget_t ntfs_vget;
static vfs_fhtovp_t ntfs_fhtovp;
static vfs_cmount_t ntfs_cmount;
static vfs_mount_t ntfs_mount;
static vfs_root_t ntfs_root;
static vfs_statfs_t ntfs_statfs;
static vfs_unmount_t ntfs_unmount;
static b_strategy_t ntfs_bufstrategy;
/*
* Buffer operations for NTFS vnodes.
* We punt on VOP_BMAP, so we need to do
* strategy on the file's vnode rather
* than the underlying device's
*/
static struct buf_ops ntfs_vnbufops = {
.bop_name = "NTFS",
.bop_strategy = ntfs_bufstrategy,
};
static int
ntfs_init (
struct vfsconf *vcp )
{
ntfs_nthashinit();
ntfs_toupper_init();
return 0;
}
static int
ntfs_uninit (
struct vfsconf *vcp )
{
ntfs_toupper_destroy();
ntfs_nthashdestroy();
return 0;
}
static int
ntfs_cmount (
struct mntarg *ma,
void *data,
uint64_t flags)
{
struct ntfs_args args;
struct export_args exp;
int error;
error = copyin(data, &args, sizeof(args));
if (error)
return (error);
vfs_oexport_conv(&args.export, &exp);
ma = mount_argsu(ma, "from", args.fspec, MAXPATHLEN);
ma = mount_arg(ma, "export", &exp, sizeof(exp));
ma = mount_argf(ma, "uid", "%d", args.uid);
ma = mount_argf(ma, "gid", "%d", args.gid);
ma = mount_argf(ma, "mode", "%d", args.mode);
ma = mount_argb(ma, args.flag & NTFS_MFLAG_CASEINS, "nocaseins");
ma = mount_argb(ma, args.flag & NTFS_MFLAG_ALLNAMES, "noallnames");
if (args.flag & NTFS_MFLAG_KICONV) {
ma = mount_argsu(ma, "cs_ntfs", args.cs_ntfs, 64);
ma = mount_argsu(ma, "cs_local", args.cs_local, 64);
}
error = kernel_mount(ma, flags);
return (error);
}
static const char *ntfs_opts[] = {
"from", "export", "uid", "gid", "mode", "caseins", "allnames",
"kiconv", "cs_ntfs", "cs_local", NULL
};
static int
ntfs_mount(struct mount *mp)
{
int err = 0, error;
struct vnode *devvp;
struct nameidata ndp;
struct thread *td;
char *from;
td = curthread;
if (vfs_filteropt(mp->mnt_optnew, ntfs_opts))
return (EINVAL);
/* Force mount as read-only. */
MNT_ILOCK(mp);
mp->mnt_flag |= MNT_RDONLY;
MNT_IUNLOCK(mp);
from = vfs_getopts(mp->mnt_optnew, "from", &error);
if (error)
return (error);
/*
* If updating, check whether changing from read-only to
* read/write.
*/
if (mp->mnt_flag & MNT_UPDATE) {
if (vfs_flagopt(mp->mnt_optnew, "export", NULL, 0)) {
/* Process export requests in vfs_mount.c */
return (0);
} else {
printf("ntfs_mount(): MNT_UPDATE not supported\n");
return (EINVAL);
}
}
/*
* Not an update, or updating the name: look up the name
* and verify that it refers to a sensible block device.
*/
NDINIT(&ndp, LOOKUP, FOLLOW | LOCKLEAF, UIO_SYSSPACE, from, td);
err = namei(&ndp);
if (err)
return (err);
NDFREE(&ndp, NDF_ONLY_PNBUF);
devvp = ndp.ni_vp;
if (!vn_isdisk(devvp, &err)) {
vput(devvp);
return (err);
}
/*
* If mount by non-root, then verify that user has necessary
* permissions on the device.
*/
err = VOP_ACCESS(devvp, VREAD, td->td_ucred, td);
if (err)
err = priv_check(td, PRIV_VFS_MOUNT_PERM);
if (err) {
vput(devvp);
return (err);
}
/*
* Since this is a new mount, we want the names for the device and
* the mount point copied in. If an error occurs, the mountpoint is
* discarded by the upper level code. Note that vfs_mount() handles
* copying the mountpoint f_mntonname for us, so we don't have to do
* it here unless we want to set it to something other than "path"
* for some rason.
*/
err = ntfs_mountfs(devvp, mp, td);
if (err == 0) {
/* Save "mounted from" info for mount point. */
vfs_mountedfrom(mp, from);
} else
vrele(devvp);
return (err);
}
/*
* Common code for mount and mountroot
*/
int
ntfs_mountfs(devvp, mp, td)
register struct vnode *devvp;
struct mount *mp;
struct thread *td;
{
struct buf *bp;
struct ntfsmount *ntmp;
struct cdev *dev = devvp->v_rdev;
int error, i, v;
struct vnode *vp;
struct g_consumer *cp;
struct g_provider *pp;
char *cs_ntfs, *cs_local;
DROP_GIANT();
g_topology_lock();
/*
* XXX: Do not allow more than one consumer to open a device
* associated with a particular GEOM provider.
* This disables multiple read-only mounts of a device,
* but it gets rid of panics in vget() when you try to
* mount the same device more than once.
*/
pp = g_dev_getprovider(devvp->v_rdev);
if ((pp != NULL) && ((pp->acr | pp->acw | pp->ace ) != 0))
error = EPERM;
else
error = g_vfs_open(devvp, &cp, "ntfs", 0);
g_topology_unlock();
PICKUP_GIANT();
VOP_UNLOCK(devvp, 0);
if (error)
return (error);
bp = NULL;
error = bread(devvp, BBLOCK, BBSIZE, NOCRED, &bp);
if (error)
goto out;
ntmp = malloc( sizeof *ntmp, M_NTFSMNT, M_WAITOK | M_ZERO);
bcopy( bp->b_data, &ntmp->ntm_bootfile, sizeof(struct bootfile) );
/*
* We must not cache the boot block if its size is not exactly
* one cluster in order to avoid confusing the buffer cache when
* the boot file is read later by ntfs_readntvattr_plain(), which
* reads a cluster at a time.
*/
if (ntfs_cntob(1) != BBSIZE)
bp->b_flags |= B_NOCACHE;
brelse( bp );
bp = NULL;
if (strncmp((const char *)ntmp->ntm_bootfile.bf_sysid, NTFS_BBID, NTFS_BBIDLEN)) {
error = EINVAL;
dprintf(("ntfs_mountfs: invalid boot block\n"));
goto out;
}
{
int8_t cpr = ntmp->ntm_mftrecsz;
if( cpr > 0 )
ntmp->ntm_bpmftrec = ntmp->ntm_spc * cpr;
else
ntmp->ntm_bpmftrec = (1 << (-cpr)) / ntmp->ntm_bps;
}
ntmp->ntm_multiplier = ntmp->ntm_bps / DEV_BSIZE;
dprintf(("ntfs_mountfs(): bps: %d, spc: %d, media: %x, mftrecsz: %d (%d sects)\n",
ntmp->ntm_bps,ntmp->ntm_spc,ntmp->ntm_bootfile.bf_media,
ntmp->ntm_mftrecsz,ntmp->ntm_bpmftrec));
dprintf(("ntfs_mountfs(): mftcn: 0x%x|0x%x\n",
(u_int32_t)ntmp->ntm_mftcn,(u_int32_t)ntmp->ntm_mftmirrcn));
ntmp->ntm_mountp = mp;
ntmp->ntm_devvp = devvp;
if (vfs_scanopt(mp->mnt_optnew, "uid", "%d", &v) == 1)
ntmp->ntm_uid = v;
if (vfs_scanopt(mp->mnt_optnew, "gid", "%d", &v) == 1)
ntmp->ntm_gid = v;
if (vfs_scanopt(mp->mnt_optnew, "mode", "%d", &v) == 1)
ntmp->ntm_mode = v & ACCESSPERMS;
vfs_flagopt(mp->mnt_optnew,
"caseins", &ntmp->ntm_flag, NTFS_MFLAG_CASEINS);
vfs_flagopt(mp->mnt_optnew,
"allnames", &ntmp->ntm_flag, NTFS_MFLAG_ALLNAMES);
ntmp->ntm_cp = cp;
ntmp->ntm_bo = &devvp->v_bufobj;
cs_local = vfs_getopts(mp->mnt_optnew, "cs_local", &error);
if (error && error != ENOENT)
goto out;
cs_ntfs = vfs_getopts(mp->mnt_optnew, "cs_ntfs", &error);
if (error && error != ENOENT)
goto out;
/* Copy in the 8-bit to Unicode conversion table */
/* Initialize Unicode to 8-bit table from 8toU table */
ntfs_82u_init(ntmp, cs_local, cs_ntfs);
if (cs_local != NULL && cs_ntfs != NULL)
ntfs_u28_init(ntmp, NULL, cs_local, cs_ntfs);
else
ntfs_u28_init(ntmp, ntmp->ntm_82u, cs_local, cs_ntfs);
mp->mnt_data = ntmp;
dprintf(("ntfs_mountfs(): case-%s,%s uid: %d, gid: %d, mode: %o\n",
(ntmp->ntm_flag & NTFS_MFLAG_CASEINS)?"insens.":"sens.",
(ntmp->ntm_flag & NTFS_MFLAG_ALLNAMES)?" allnames,":"",
ntmp->ntm_uid, ntmp->ntm_gid, ntmp->ntm_mode));
/*
* We read in some system nodes to do not allow
* reclaim them and to have everytime access to them.
*/
{
int pi[3] = { NTFS_MFTINO, NTFS_ROOTINO, NTFS_BITMAPINO };
for (i=0; i<3; i++) {
error = VFS_VGET(mp, pi[i], LK_EXCLUSIVE,
&(ntmp->ntm_sysvn[pi[i]]));
if(error)
goto out1;
ntmp->ntm_sysvn[pi[i]]->v_vflag |= VV_SYSTEM;
VREF(ntmp->ntm_sysvn[pi[i]]);
vput(ntmp->ntm_sysvn[pi[i]]);
}
}
/* read the Unicode lowercase --> uppercase translation table,
* if necessary */
if ((error = ntfs_toupper_use(mp, ntmp)))
goto out1;
/*
* Scan $BitMap and count free clusters
*/
error = ntfs_calccfree(ntmp, &ntmp->ntm_cfree);
if(error)
goto out1;
/*
* Read and translate to internal format attribute
* definition file.
*/
{
int num,j;
struct attrdef ad;
/* Open $AttrDef */
error = VFS_VGET(mp, NTFS_ATTRDEFINO, LK_EXCLUSIVE, &vp );
if(error)
goto out1;
/* Count valid entries */
for(num=0;;num++) {
error = ntfs_readattr(ntmp, VTONT(vp),
NTFS_A_DATA, NULL,
num * sizeof(ad), sizeof(ad),
&ad, NULL);
if (error)
goto out1;
if (ad.ad_name[0] == 0)
break;
}
/* Alloc memory for attribute definitions */
ntmp->ntm_ad = malloc(num * sizeof(struct ntvattrdef),
M_NTFSMNT, M_WAITOK);
ntmp->ntm_adnum = num;
/* Read them and translate */
for(i=0;i<num;i++){
error = ntfs_readattr(ntmp, VTONT(vp),
NTFS_A_DATA, NULL,
i * sizeof(ad), sizeof(ad),
&ad, NULL);
if (error)
goto out1;
j = 0;
do {
ntmp->ntm_ad[i].ad_name[j] = ad.ad_name[j];
} while(ad.ad_name[j++]);
ntmp->ntm_ad[i].ad_namelen = j - 1;
ntmp->ntm_ad[i].ad_type = ad.ad_type;
}
vput(vp);
}
mp->mnt_stat.f_fsid.val[0] = dev2udev(dev);
mp->mnt_stat.f_fsid.val[1] = mp->mnt_vfc->vfc_typenum;
mp->mnt_maxsymlinklen = 0;
MNT_ILOCK(mp);
mp->mnt_flag |= MNT_LOCAL;
MNT_IUNLOCK(mp);
return (0);
out1:
for(i=0;i<NTFS_SYSNODESNUM;i++)
if(ntmp->ntm_sysvn[i]) vrele(ntmp->ntm_sysvn[i]);
if (vflush(mp, 0, 0, td))
dprintf(("ntfs_mountfs: vflush failed\n"));
out:
if (bp)
brelse(bp);
DROP_GIANT();
g_topology_lock();
g_vfs_close(cp);
g_topology_unlock();
PICKUP_GIANT();
return (error);
}
static int
ntfs_unmount(
struct mount *mp,
int mntflags)
{
struct thread *td;
struct ntfsmount *ntmp;
int error, flags, i;
dprintf(("ntfs_unmount: unmounting...\n"));
td = curthread;
ntmp = VFSTONTFS(mp);
flags = 0;
if(mntflags & MNT_FORCE)
flags |= FORCECLOSE;
dprintf(("ntfs_unmount: vflushing...\n"));
error = vflush(mp, 0, flags | SKIPSYSTEM, td);
if (error) {
printf("ntfs_unmount: vflush failed: %d\n",error);
return (error);
}
/* Check if only system vnodes are rest */
for(i=0;i<NTFS_SYSNODESNUM;i++)
if((ntmp->ntm_sysvn[i]) &&
(vrefcnt(ntmp->ntm_sysvn[i]) > 1)) return (EBUSY);
/* Dereference all system vnodes */
for(i=0;i<NTFS_SYSNODESNUM;i++)
if(ntmp->ntm_sysvn[i]) vrele(ntmp->ntm_sysvn[i]);
/* vflush system vnodes */
error = vflush(mp, 0, flags, td);
if (error)
printf("ntfs_unmount: vflush failed(sysnodes): %d\n",error);
vinvalbuf(ntmp->ntm_devvp, V_SAVE, 0, 0);
DROP_GIANT();
g_topology_lock();
g_vfs_close(ntmp->ntm_cp);
g_topology_unlock();
PICKUP_GIANT();
vrele(ntmp->ntm_devvp);
/* free the toupper table, if this has been last mounted ntfs volume */
ntfs_toupper_unuse();
dprintf(("ntfs_umount: freeing memory...\n"));
ntfs_u28_uninit(ntmp);
ntfs_82u_uninit(ntmp);
mp->mnt_data = NULL;
MNT_ILOCK(mp);
mp->mnt_flag &= ~MNT_LOCAL;
MNT_IUNLOCK(mp);
free(ntmp->ntm_ad, M_NTFSMNT);
free(ntmp, M_NTFSMNT);
return (error);
}
static int
ntfs_root(
struct mount *mp,
int flags,
struct vnode **vpp)
{
struct vnode *nvp;
int error = 0;
dprintf(("ntfs_root(): sysvn: %p\n",
VFSTONTFS(mp)->ntm_sysvn[NTFS_ROOTINO]));
error = VFS_VGET(mp, (ino_t)NTFS_ROOTINO, LK_EXCLUSIVE, &nvp);
if(error) {
printf("ntfs_root: VFS_VGET failed: %d\n",error);
return (error);
}
*vpp = nvp;
return (0);
}
static int
ntfs_calccfree(
struct ntfsmount *ntmp,
cn_t *cfreep)
{
struct vnode *vp;
u_int8_t *tmp;
int j, error;
long cfree = 0;
size_t bmsize, i;
vp = ntmp->ntm_sysvn[NTFS_BITMAPINO];
bmsize = VTOF(vp)->f_size;
tmp = malloc(bmsize, M_TEMP, M_WAITOK);
error = ntfs_readattr(ntmp, VTONT(vp), NTFS_A_DATA, NULL,
0, bmsize, tmp, NULL);
if (error)
goto out;
for(i=0;i<bmsize;i++)
for(j=0;j<8;j++)
if(~tmp[i] & (1 << j)) cfree++;
*cfreep = cfree;
out:
free(tmp, M_TEMP);
return(error);
}
static int
ntfs_statfs(
struct mount *mp,
struct statfs *sbp)
{
struct ntfsmount *ntmp = VFSTONTFS(mp);
u_int64_t mftsize,mftallocated;
dprintf(("ntfs_statfs():\n"));
mftsize = VTOF(ntmp->ntm_sysvn[NTFS_MFTINO])->f_size;
mftallocated = VTOF(ntmp->ntm_sysvn[NTFS_MFTINO])->f_allocated;
sbp->f_type = mp->mnt_vfc->vfc_typenum;
sbp->f_bsize = ntmp->ntm_bps;
sbp->f_iosize = ntmp->ntm_bps * ntmp->ntm_spc;
sbp->f_blocks = ntmp->ntm_bootfile.bf_spv;
sbp->f_bfree = sbp->f_bavail = ntfs_cntobn(ntmp->ntm_cfree);
sbp->f_ffree = sbp->f_bfree / ntmp->ntm_bpmftrec;
sbp->f_files = mftallocated / ntfs_bntob(ntmp->ntm_bpmftrec) +
sbp->f_ffree;
sbp->f_flags = mp->mnt_flag;
return (0);
}
/*ARGSUSED*/
static int
ntfs_fhtovp(
struct mount *mp,
struct fid *fhp,
int flags,
struct vnode **vpp)
{
struct vnode *nvp;
struct ntfid *ntfhp = (struct ntfid *)fhp;
int error;
ddprintf(("ntfs_fhtovp(): %d\n", ntfhp->ntfid_ino));
if ((error = VFS_VGET(mp, ntfhp->ntfid_ino, LK_EXCLUSIVE, &nvp)) != 0) {
*vpp = NULLVP;
return (error);
}
/* XXX as unlink/rmdir/mkdir/creat are not currently possible
* with NTFS, we don't need to check anything else for now */
*vpp = nvp;
vnode_create_vobject(nvp, VTOF(nvp)->f_size, curthread);
return (0);
}
int
ntfs_vgetex(
struct mount *mp,
ino_t ino,
u_int32_t attrtype,
char *attrname,
u_long lkflags,
u_long flags,
struct thread *td,
struct vnode **vpp)
{
int error;
register struct ntfsmount *ntmp;
struct ntnode *ip;
struct fnode *fp;
struct vnode *vp;
enum vtype f_type;
dprintf(("ntfs_vgetex: ino: %ju, attr: 0x%x:%s, lkf: 0x%lx, f: 0x%lx\n",
(uintmax_t)ino, attrtype, attrname ? attrname : "", lkflags,
(u_long)flags));
ntmp = VFSTONTFS(mp);
*vpp = NULL;
/* Get ntnode */
error = ntfs_ntlookup(ntmp, ino, &ip);
if (error) {
printf("ntfs_vget: ntfs_ntget failed\n");
return (error);
}
/* It may be not initialized fully, so force load it */
if (!(flags & VG_DONTLOADIN) && !(ip->i_flag & IN_LOADED)) {
error = ntfs_loadntnode(ntmp, ip);
if(error) {
printf("ntfs_vget: CAN'T LOAD ATTRIBUTES FOR INO: %ju\n",
(uintmax_t)ip->i_number);
ntfs_ntput(ip);
return (error);
}
}
error = ntfs_fget(ntmp, ip, attrtype, attrname, &fp);
if (error) {
printf("ntfs_vget: ntfs_fget failed\n");
ntfs_ntput(ip);
return (error);
}
f_type = VNON;
if (!(flags & VG_DONTVALIDFN) && !(fp->f_flag & FN_VALID)) {
if ((ip->i_frflag & NTFS_FRFLAG_DIR) &&
(fp->f_attrtype == NTFS_A_DATA && fp->f_attrname == NULL)) {
f_type = VDIR;
} else if (flags & VG_EXT) {
f_type = VNON;
fp->f_size = fp->f_allocated = 0;
} else {
f_type = VREG;
error = ntfs_filesize(ntmp, fp,
&fp->f_size, &fp->f_allocated);
if (error) {
ntfs_ntput(ip);
return (error);
}
}
fp->f_flag |= FN_VALID;
}
if (FTOV(fp)) {
vget(FTOV(fp), lkflags, td);
*vpp = FTOV(fp);
ntfs_ntput(ip);
return (0);
}
error = getnewvnode("ntfs", ntmp->ntm_mountp, &ntfs_vnodeops, &vp);
if(error) {
ntfs_frele(fp);
ntfs_ntput(ip);
return (error);
}
/* XXX: Too early for mpsafe fs, lacks vnode lock */
error = insmntque(vp, ntmp->ntm_mountp);
if (error) {
ntfs_frele(fp);
ntfs_ntput(ip);
return (error);
}
dprintf(("ntfs_vget: vnode: %p for ntnode: %ju\n", vp, (uintmax_t)ino));
fp->f_vp = vp;
vp->v_data = fp;
vp->v_type = f_type;
vp->v_bufobj.bo_ops = &ntfs_vnbufops;
vp->v_bufobj.bo_private = vp;
if (ino == NTFS_ROOTINO)
vp->v_vflag |= VV_ROOT;
ntfs_ntput(ip);
if (lkflags & LK_TYPE_MASK) {
error = vn_lock(vp, lkflags);
if (error) {
vput(vp);
return (error);
}
}
*vpp = vp;
return (0);
}
static int
ntfs_vget(
struct mount *mp,
ino_t ino,
int lkflags,
struct vnode **vpp)
{
return ntfs_vgetex(mp, ino, NTFS_A_DATA, NULL, lkflags, 0,
curthread, vpp);
}
static void
ntfs_bufstrategy(struct bufobj *bo, struct buf *bp)
{
struct vnode *vp;
int rc;
vp = bo->bo_private;
KASSERT(bo == &vp->v_bufobj, ("BO/VP mismatch: vp %p bo %p != %p",
vp, &vp->v_bufobj, bo));
rc = VOP_STRATEGY(vp, bp);
KASSERT(rc == 0, ("NTFS VOP_STRATEGY failed: bp=%p, "
"vp=%p, rc=%d", bp, vp, rc));
}
static struct vfsops ntfs_vfsops = {
.vfs_fhtovp = ntfs_fhtovp,
.vfs_init = ntfs_init,
.vfs_cmount = ntfs_cmount,
.vfs_mount = ntfs_mount,
.vfs_root = ntfs_root,
.vfs_statfs = ntfs_statfs,
.vfs_uninit = ntfs_uninit,
.vfs_unmount = ntfs_unmount,
.vfs_vget = ntfs_vget,
};
VFS_SET(ntfs_vfsops, ntfs, VFCF_READONLY);
MODULE_VERSION(ntfs, 1);

View File

@ -1,43 +0,0 @@
/* $NetBSD: ntfs_vfsops.h,v 1.4 1999/10/10 14:20:33 jdolecek Exp $ */
/*-
* Copyright (c) 1998, 1999 Semen Ustimenko (semenu@FreeBSD.org)
* 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.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
*
* $FreeBSD$
*/
#define VG_DONTLOADIN 0x0001 /* Tells ntfs_vgetex to do not call */
/* ntfs_loadntnode() on ntnode, even if */
/* ntnode not loaded */
#define VG_DONTVALIDFN 0x0002 /* Tells ntfs_vgetex to do not validate */
/* fnode */
#define VG_EXT 0x0004 /* This is not main record */
struct mount;
struct ntfsmount;
struct thread;
struct vnode;
int ntfs_vgetex(struct mount *, ino_t, u_int32_t, char *, u_long, u_long,
struct thread *, struct vnode **);

View File

@ -1,687 +0,0 @@
/* $NetBSD: ntfs_vnops.c,v 1.23 1999/10/31 19:45:27 jdolecek Exp $ */
/*-
* Copyright (c) 1992, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* John Heidemann of the UCLA Ficus project.
*
* 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.
* 4. Neither the name of the University 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 REGENTS 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 REGENTS 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.
*
* $FreeBSD$
*
*/
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/vnode.h>
#include <sys/mount.h>
#include <sys/namei.h>
#include <sys/malloc.h>
#include <sys/bio.h>
#include <sys/buf.h>
#include <sys/dirent.h>
#include <vm/vm.h>
#include <vm/vm_param.h>
#include <vm/vm_page.h>
#include <vm/vm_object.h>
#include <vm/vm_pager.h>
#include <vm/vnode_pager.h>
#include <vm/vm_extern.h>
#include <sys/sysctl.h>
/*#define NTFS_DEBUG 1*/
#include <fs/ntfs/ntfs.h>
#include <fs/ntfs/ntfs_inode.h>
#include <fs/ntfs/ntfs_subr.h>
#include <sys/unistd.h> /* for pathconf(2) constants */
static vop_read_t ntfs_read;
static vop_getattr_t ntfs_getattr;
static vop_inactive_t ntfs_inactive;
static vop_reclaim_t ntfs_reclaim;
static vop_bmap_t ntfs_bmap;
static vop_strategy_t ntfs_strategy;
static vop_access_t ntfs_access;
static vop_open_t ntfs_open;
static vop_close_t ntfs_close;
static vop_readdir_t ntfs_readdir;
static vop_cachedlookup_t ntfs_lookup;
static vop_pathconf_t ntfs_pathconf;
static vop_vptofh_t ntfs_vptofh;
/*
* This is a noop, simply returning what one has been given.
*/
int
ntfs_bmap(ap)
struct vop_bmap_args /* {
struct vnode *a_vp;
daddr_t a_bn;
struct bufobj **a_bop;
daddr_t *a_bnp;
int *a_runp;
int *a_runb;
} */ *ap;
{
struct vnode *vp = ap->a_vp;
dprintf(("ntfs_bmap: vn: %p, blk: %d\n", ap->a_vp,(u_int32_t)ap->a_bn));
if (ap->a_bop != NULL)
*ap->a_bop = &vp->v_bufobj;
if (ap->a_bnp != NULL)
*ap->a_bnp = ap->a_bn;
if (ap->a_runp != NULL)
*ap->a_runp = 0;
if (ap->a_runb != NULL)
*ap->a_runb = 0;
return (0);
}
static int
ntfs_read(ap)
struct vop_read_args /* {
struct vnode *a_vp;
struct uio *a_uio;
int a_ioflag;
struct ucred *a_cred;
} */ *ap;
{
register struct vnode *vp = ap->a_vp;
register struct fnode *fp = VTOF(vp);
register struct ntnode *ip = FTONT(fp);
struct uio *uio = ap->a_uio;
struct ntfsmount *ntmp = ip->i_mp;
struct buf *bp;
daddr_t cn;
int resid, off, toread;
int error;
dprintf(("ntfs_read: ino: %ju, off: %jd resid: %d, segflg: %d\n",
(uintmax_t)ip->i_number, (intmax_t)uio->uio_offset,
uio->uio_resid, uio->uio_segflg));
dprintf(("ntfs_read: filesize: %d",(u_int32_t)fp->f_size));
/* don't allow reading after end of file */
if (uio->uio_offset > fp->f_size)
return (0);
resid = MIN(uio->uio_resid, fp->f_size - uio->uio_offset);
dprintf((", resid: %d\n", resid));
error = 0;
while (resid) {
cn = ntfs_btocn(uio->uio_offset);
off = ntfs_btocnoff(uio->uio_offset);
toread = MIN(off + resid, ntfs_cntob(1));
error = bread(vp, cn, ntfs_cntob(1), NOCRED, &bp);
if (error) {
brelse(bp);
break;
}
error = uiomove(bp->b_data + off, toread - off, uio);
if(error) {
brelse(bp);
break;
}
brelse(bp);
resid -= toread - off;
}
return (error);
}
static int
ntfs_getattr(ap)
struct vop_getattr_args /* {
struct vnode *a_vp;
struct vattr *a_vap;
struct ucred *a_cred;
struct thread *a_td;
} */ *ap;
{
register struct vnode *vp = ap->a_vp;
register struct fnode *fp = VTOF(vp);
register struct ntnode *ip = FTONT(fp);
register struct vattr *vap = ap->a_vap;
dprintf(("ntfs_getattr: %ju, flags: %d\n",
(uintmax_t)ip->i_number, ip->i_flag));
vap->va_fsid = dev2udev(ip->i_dev);
vap->va_fileid = ip->i_number;
vap->va_mode = ip->i_mp->ntm_mode;
vap->va_nlink = (ip->i_nlink || ip->i_flag & IN_LOADED ? ip->i_nlink : 1);
vap->va_uid = ip->i_mp->ntm_uid;
vap->va_gid = ip->i_mp->ntm_gid;
vap->va_rdev = NODEV;
vap->va_size = fp->f_size;
vap->va_bytes = fp->f_allocated;
vap->va_atime = ntfs_nttimetounix(fp->f_times.t_access);
vap->va_mtime = ntfs_nttimetounix(fp->f_times.t_write);
vap->va_ctime = ntfs_nttimetounix(fp->f_times.t_create);
vap->va_flags = ip->i_flag;
vap->va_gen = 0;
vap->va_blocksize = ip->i_mp->ntm_spc * ip->i_mp->ntm_bps;
vap->va_type = vp->v_type;
vap->va_filerev = 0;
return (0);
}
/*
* Last reference to an ntnode. If necessary, write or delete it.
*/
int
ntfs_inactive(ap)
struct vop_inactive_args /* {
struct vnode *a_vp;
} */ *ap;
{
#ifdef NTFS_DEBUG
register struct ntnode *ip = VTONT(ap->a_vp);
#endif
dprintf(("ntfs_inactive: vnode: %p, ntnode: %ju\n", ap->a_vp,
(uintmax_t)ip->i_number));
/* XXX since we don't support any filesystem changes
* right now, nothing more needs to be done
*/
return (0);
}
/*
* Reclaim an fnode/ntnode so that it can be used for other purposes.
*/
int
ntfs_reclaim(ap)
struct vop_reclaim_args /* {
struct vnode *a_vp;
} */ *ap;
{
register struct vnode *vp = ap->a_vp;
register struct fnode *fp = VTOF(vp);
register struct ntnode *ip = FTONT(fp);
int error;
dprintf(("ntfs_reclaim: vnode: %p, ntnode: %ju\n",
vp, (uintmax_t)ip->i_number));
/*
* Destroy the vm object and flush associated pages.
*/
vnode_destroy_vobject(vp);
if ((error = ntfs_ntget(ip)) != 0)
return (error);
/* Purge old data structures associated with the inode. */
ntfs_frele(fp);
ntfs_ntput(ip);
vp->v_data = NULL;
return (0);
}
/*
* Calculate the logical to physical mapping if not done already,
* then call the device strategy routine.
*/
int
ntfs_strategy(ap)
struct vop_strategy_args /* {
struct buf *a_bp;
} */ *ap;
{
register struct buf *bp = ap->a_bp;
register struct vnode *vp = ap->a_vp;
register struct fnode *fp = VTOF(vp);
register struct ntnode *ip = FTONT(fp);
struct ntfsmount *ntmp = ip->i_mp;
u_int32_t toread;
int error;
dprintf(("ntfs_strategy: offset: %d, blkno: %d, lblkno: %d\n",
(u_int32_t)bp->b_offset,(u_int32_t)bp->b_blkno,
(u_int32_t)bp->b_lblkno));
dprintf(("strategy: bcount: %d flags: 0x%x\n",
(u_int32_t)bp->b_bcount,bp->b_flags));
KASSERT(bp->b_iocmd == BIO_READ, ("Invalid buffer\n"));
if (ntfs_cntob(bp->b_blkno) >= fp->f_size) {
clrbuf(bp);
error = 0;
} else {
toread = MIN(bp->b_bcount,
fp->f_size-ntfs_cntob(bp->b_blkno));
dprintf(("ntfs_strategy: toread: %d, fsize: %d\n",
toread,(u_int32_t)fp->f_size));
error = ntfs_readattr(ntmp, ip, fp->f_attrtype,
fp->f_attrname, ntfs_cntob(bp->b_blkno),
toread, bp->b_data, NULL);
if (error) {
printf("ntfs_strategy: ntfs_readattr failed\n");
bp->b_error = error;
bp->b_ioflags |= BIO_ERROR;
}
bzero(bp->b_data + toread, bp->b_bcount - toread);
}
bufdone(bp);
return (0);
}
int
ntfs_access(ap)
struct vop_access_args /* {
struct vnode *a_vp;
accmode_t a_accmode;
struct ucred *a_cred;
struct thread *a_td;
} */ *ap;
{
struct vnode *vp = ap->a_vp;
struct ntnode *ip = VTONT(vp);
accmode_t accmode = ap->a_accmode;
dprintf(("ntfs_access: %d\n",ip->i_number));
/*
* Disallow write attempts as we assume read-only filesystems;
* unless the file is a socket, fifo, or a block or
* character device resident on the filesystem.
*/
if (accmode & VWRITE) {
switch ((int)vp->v_type) {
case VDIR:
case VLNK:
case VREG:
return (EROFS);
default:
break;
}
}
return (vaccess(vp->v_type, ip->i_mp->ntm_mode, ip->i_mp->ntm_uid,
ip->i_mp->ntm_gid, ap->a_accmode, ap->a_cred, NULL));
}
/*
* Open called.
*
* Nothing to do.
*/
/* ARGSUSED */
static int
ntfs_open(ap)
struct vop_open_args /* {
struct vnode *a_vp;
int a_mode;
struct ucred *a_cred;
struct thread *a_td;
} */ *ap;
{
#ifdef NTFS_DEBUG
register struct vnode *vp = ap->a_vp;
register struct ntnode *ip = VTONT(vp);
printf("ntfs_open: %d\n",ip->i_number);
#endif
vnode_create_vobject(ap->a_vp, VTOF(ap->a_vp)->f_size, ap->a_td);
/*
* Files marked append-only must be opened for appending.
*/
return (0);
}
/*
* Close called.
*
* Update the times on the inode.
*/
/* ARGSUSED */
static int
ntfs_close(ap)
struct vop_close_args /* {
struct vnode *a_vp;
int a_fflag;
struct ucred *a_cred;
struct thread *a_td;
} */ *ap;
{
#ifdef NTFS_DEBUG
register struct vnode *vp = ap->a_vp;
register struct ntnode *ip = VTONT(vp);
printf("ntfs_close: %d\n",ip->i_number);
#endif
return (0);
}
int
ntfs_readdir(ap)
struct vop_readdir_args /* {
struct vnode *a_vp;
struct uio *a_uio;
struct ucred *a_cred;
int *a_ncookies;
u_int **cookies;
} */ *ap;
{
register struct vnode *vp = ap->a_vp;
register struct fnode *fp = VTOF(vp);
register struct ntnode *ip = FTONT(fp);
struct uio *uio = ap->a_uio;
struct ntfsmount *ntmp = ip->i_mp;
int i, j, error = 0;
char *c, tmpbuf[5];
u_int32_t faked = 0, num;
int ncookies = 0;
struct dirent cde;
off_t off;
dprintf(("ntfs_readdir %d off: %d resid: %d\n",ip->i_number,(u_int32_t)uio->uio_offset,uio->uio_resid));
off = uio->uio_offset;
/* Simulate . in every dir except ROOT */
if( ip->i_number != NTFS_ROOTINO ) {
struct dirent dot = {
.d_fileno = NTFS_ROOTINO,
.d_reclen = sizeof(struct dirent),
.d_type = DT_DIR,
.d_namlen = 1,
.d_name = "."
};
if( uio->uio_offset < sizeof(struct dirent) ) {
dot.d_fileno = ip->i_number;
error = uiomove((char *)&dot,sizeof(struct dirent),uio);
if(error)
return (error);
ncookies ++;
}
}
/* Simulate .. in every dir including ROOT */
if( uio->uio_offset < 2 * sizeof(struct dirent) ) {
struct dirent dotdot = {
.d_fileno = NTFS_ROOTINO,
.d_reclen = sizeof(struct dirent),
.d_type = DT_DIR,
.d_namlen = 2,
.d_name = ".."
};
error = uiomove((char *)&dotdot,sizeof(struct dirent),uio);
if(error)
return (error);
ncookies ++;
}
faked = (ip->i_number == NTFS_ROOTINO) ? 1 : 2;
num = uio->uio_offset / sizeof(struct dirent) - faked;
while( uio->uio_resid >= sizeof(struct dirent) ) {
struct attr_indexentry *iep;
error = ntfs_ntreaddir(ntmp, fp, num, &iep);
if(error)
return (error);
if( NULL == iep )
break;
for(; !(iep->ie_flag & NTFS_IEFLAG_LAST) && (uio->uio_resid >= sizeof(struct dirent));
iep = NTFS_NEXTREC(iep, struct attr_indexentry *))
{
if(!ntfs_isnamepermitted(ntmp,iep))
continue;
for(i=0, j=0; i<iep->ie_fnamelen; i++) {
c = NTFS_U28(iep->ie_fname[i]);
while (*c != '\0')
cde.d_name[j++] = *c++;
}
cde.d_name[j] = '\0';
dprintf(("ntfs_readdir: elem: %d, fname:[%s] type: %d, flag: %d, ",
num, cde.d_name, iep->ie_fnametype,
iep->ie_flag));
cde.d_namlen = j;
cde.d_fileno = iep->ie_number;
cde.d_type = (iep->ie_fflag & NTFS_FFLAG_DIR) ? DT_DIR : DT_REG;
cde.d_reclen = sizeof(struct dirent);
dprintf(("%s\n", (cde.d_type == DT_DIR) ? "dir":"reg"));
error = uiomove((char *)&cde, sizeof(struct dirent), uio);
if(error)
return (error);
ncookies++;
num++;
}
}
dprintf(("ntfs_readdir: %d entries (%d bytes) read\n",
ncookies,(u_int)(uio->uio_offset - off)));
dprintf(("ntfs_readdir: off: %d resid: %d\n",
(u_int32_t)uio->uio_offset,uio->uio_resid));
if (!error && ap->a_ncookies != NULL) {
struct dirent* dpStart;
struct dirent* dp;
u_long *cookies;
u_long *cookiep;
ddprintf(("ntfs_readdir: %d cookies\n",ncookies));
if (uio->uio_segflg != UIO_SYSSPACE || uio->uio_iovcnt != 1)
panic("ntfs_readdir: unexpected uio from NFS server");
dpStart = (struct dirent *)
((caddr_t)uio->uio_iov->iov_base -
(uio->uio_offset - off));
cookies = malloc(ncookies * sizeof(u_long),
M_TEMP, M_WAITOK);
for (dp = dpStart, cookiep = cookies, i=0;
i < ncookies;
dp = (struct dirent *)((caddr_t) dp + dp->d_reclen), i++) {
off += dp->d_reclen;
*cookiep++ = (u_int) off;
}
*ap->a_ncookies = ncookies;
*ap->a_cookies = cookies;
}
/*
if (ap->a_eofflag)
*ap->a_eofflag = VTONT(ap->a_vp)->i_size <= uio->uio_offset;
*/
return (error);
}
int
ntfs_lookup(ap)
struct vop_cachedlookup_args /* {
struct vnode *a_dvp;
struct vnode **a_vpp;
struct componentname *a_cnp;
} */ *ap;
{
register struct vnode *dvp = ap->a_dvp;
register struct ntnode *dip = VTONT(dvp);
struct ntfsmount *ntmp = dip->i_mp;
struct componentname *cnp = ap->a_cnp;
struct ucred *cred = cnp->cn_cred;
int error;
dprintf(("ntfs_lookup: \"%.*s\" (%ld bytes) in %d\n",
(int)cnp->cn_namelen, cnp->cn_nameptr, cnp->cn_namelen,
dip->i_number));
error = VOP_ACCESS(dvp, VEXEC, cred, cnp->cn_thread);
if(error)
return (error);
if ((cnp->cn_flags & ISLASTCN) &&
(cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME))
return (EROFS);
if(cnp->cn_namelen == 1 && cnp->cn_nameptr[0] == '.') {
dprintf(("ntfs_lookup: faking . directory in %d\n",
dip->i_number));
VREF(dvp);
*ap->a_vpp = dvp;
error = 0;
} else if (cnp->cn_flags & ISDOTDOT) {
struct ntvattr *vap;
dprintf(("ntfs_lookup: faking .. directory in %d\n",
dip->i_number));
error = ntfs_ntvattrget(ntmp, dip, NTFS_A_NAME, NULL, 0, &vap);
if(error)
return (error);
VOP_UNLOCK(dvp,0);
dprintf(("ntfs_lookup: parentdir: %d\n",
vap->va_a_name->n_pnumber));
error = VFS_VGET(ntmp->ntm_mountp, vap->va_a_name->n_pnumber,
LK_EXCLUSIVE, ap->a_vpp);
ntfs_ntvattrrele(vap);
if (error) {
vn_lock(dvp,LK_EXCLUSIVE|LK_RETRY);
return (error);
}
} else {
error = ntfs_ntlookupfile(ntmp, dvp, cnp, ap->a_vpp);
if (error) {
dprintf(("ntfs_ntlookupfile: returned %d\n", error));
return (error);
}
dprintf(("ntfs_lookup: found ino: %ju\n",
(uintmax_t)VTONT(*ap->a_vpp)->i_number));
}
if (cnp->cn_flags & MAKEENTRY)
cache_enter(dvp, *ap->a_vpp, cnp);
return (error);
}
/*
* Return POSIX pathconf information applicable to NTFS filesystem
*/
int
ntfs_pathconf(ap)
struct vop_pathconf_args *ap;
{
switch (ap->a_name) {
case _PC_LINK_MAX:
*ap->a_retval = 1;
return (0);
case _PC_NAME_MAX:
*ap->a_retval = NTFS_MAXFILENAME;
return (0);
case _PC_PATH_MAX:
*ap->a_retval = PATH_MAX;
return (0);
case _PC_CHOWN_RESTRICTED:
*ap->a_retval = 1;
return (0);
case _PC_NO_TRUNC:
*ap->a_retval = 0;
return (0);
default:
return (EINVAL);
}
/* NOTREACHED */
}
int
ntfs_vptofh(ap)
struct vop_vptofh_args /* {
struct vnode *a_vp;
struct fid *a_fhp;
} */ *ap;
{
register struct ntnode *ntp;
register struct ntfid *ntfhp;
ddprintf(("ntfs_fhtovp(): %p\n", ap->a_vp));
ntp = VTONT(ap->a_vp);
ntfhp = (struct ntfid *)ap->a_fhp;
ntfhp->ntfid_len = sizeof(struct ntfid);
ntfhp->ntfid_ino = ntp->i_number;
/* ntfhp->ntfid_gen = ntp->i_gen; */
return (0);
}
/*
* Global vfs data structures
*/
struct vop_vector ntfs_vnodeops = {
.vop_default = &default_vnodeops,
.vop_access = ntfs_access,
.vop_bmap = ntfs_bmap,
.vop_cachedlookup = ntfs_lookup,
.vop_close = ntfs_close,
.vop_getattr = ntfs_getattr,
.vop_inactive = ntfs_inactive,
.vop_lookup = vfs_cache_lookup,
.vop_open = ntfs_open,
.vop_pathconf = ntfs_pathconf,
.vop_read = ntfs_read,
.vop_readdir = ntfs_readdir,
.vop_reclaim = ntfs_reclaim,
.vop_strategy = ntfs_strategy,
.vop_vptofh = ntfs_vptofh,
};

View File

@ -1,44 +0,0 @@
/* $NetBSD: ntfsmount.h,v 1.3 1999/07/26 14:02:32 jdolecek Exp $ */
/*-
* Copyright (c) 1998, 1999 Semen Ustimenko
* 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.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
*
* $FreeBSD$
*/
#define NTFS_MFLAG_CASEINS 0x00000001
#define NTFS_MFLAG_ALLNAMES 0x00000002
#define NTFS_MFLAG_KICONV 0x00000004
struct ntfs_args {
char *fspec; /* block special device to mount */
struct oexport_args export; /* network export information */
uid_t uid; /* uid that owns ntfs files */
gid_t gid; /* gid that owns ntfs files */
mode_t mode; /* mask to be applied for ntfs perms */
u_long flag; /* additional flags */
char *cs_ntfs; /* NTFS Charset */
char *cs_local; /* Local Charset */
};

View File

@ -1,67 +0,0 @@
/*-
* Copyright (c) 1992, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software donated to Berkeley by
* Jan-Simon Pendry.
*
* 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.
* 4. Neither the name of the University 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 REGENTS 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 REGENTS 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.
*
* @(#)portal.h 8.4 (Berkeley) 1/21/94
*
* $FreeBSD$
*/
struct portal_args {
char *pa_config; /* Config file */
int pa_socket; /* Socket to server */
};
struct portal_cred {
int pcr_flag; /* File open mode */
uid_t pcr_uid; /* From ucred */
short pcr_ngroups; /* From ucred */
gid_t pcr_groups[XU_NGROUPS]; /* From ucred */
};
#ifdef _KERNEL
struct portalmount {
struct vnode *pm_root; /* Root node */
struct file *pm_server; /* Held reference to server socket */
};
struct portalnode {
int pt_size; /* Length of Arg */
char *pt_arg; /* Arg to send to server */
int pt_fileid; /* cookie */
};
#define VFSTOPORTAL(mp) ((struct portalmount *)((mp)->mnt_data))
#define VTOPORTAL(vp) ((struct portalnode *)(vp)->v_data)
#define PORTAL_ROOTFILEID 2
extern struct vop_vector portal_vnodeops;
#endif /* _KERNEL */

View File

@ -1,263 +0,0 @@
/*-
* Copyright (c) 1992, 1993, 1995
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software donated to Berkeley by
* Jan-Simon Pendry.
*
* 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.
* 4. Neither the name of the University 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 REGENTS 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 REGENTS 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.
*
* @(#)portal_vfsops.c 8.11 (Berkeley) 5/14/95
*
* $FreeBSD$
*/
/*
* Portal Filesystem
*/
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/capability.h>
#include <sys/domain.h>
#include <sys/filedesc.h>
#include <sys/kernel.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/malloc.h>
#include <sys/file.h> /* Must come after sys/malloc.h */
#include <sys/mount.h>
#include <sys/proc.h>
#include <sys/protosw.h>
#include <sys/socket.h>
#include <sys/socketvar.h>
#include <sys/vnode.h>
#include <fs/portalfs/portal.h>
static MALLOC_DEFINE(M_PORTALFSMNT, "portal_mount", "PORTAL mount structure");
static vfs_unmount_t portal_unmount;
static vfs_root_t portal_root;
static vfs_statfs_t portal_statfs;
static const char *portal_opts[] = {
"socket", "config",
NULL
};
static int
portal_cmount(struct mntarg *ma, void *data, uint64_t flags)
{
struct portal_args args;
int error;
if (data == NULL)
return (EINVAL);
error = copyin(data, &args, sizeof args);
if (error)
return (error);
ma = mount_argf(ma, "socket", "%d", args.pa_socket);
ma = mount_argsu(ma, "config", args.pa_config, MAXPATHLEN);
error = kernel_mount(ma, flags);
return (error);
}
/*
* Mount the per-process file descriptors (/dev/fd)
*/
static int
portal_mount(struct mount *mp)
{
struct file *fp;
struct portalmount *fmp;
struct socket *so;
struct vnode *rvp;
struct thread *td;
struct portalnode *pn;
int error, v;
char *p;
td = curthread;
if (vfs_filteropt(mp->mnt_optnew, portal_opts))
return (EINVAL);
error = vfs_scanopt(mp->mnt_optnew, "socket", "%d", &v);
if (error != 1)
return (EINVAL);
error = vfs_getopt(mp->mnt_optnew, "config", (void **)&p, NULL);
if (error)
return (error);
/*
* Capsicum is not incompatible with portalfs, but we don't really
* know what rights are required. In the spirit of "better safe than
* sorry", pretend that all rights are required for now.
*/
if ((error = fget(td, v, CAP_MASK_VALID, &fp)) != 0)
return (error);
if (fp->f_type != DTYPE_SOCKET) {
fdrop(fp, td);
return(ENOTSOCK);
}
so = fp->f_data; /* XXX race against userland */
if (so->so_proto->pr_domain->dom_family != AF_UNIX) {
fdrop(fp, td);
return (ESOCKTNOSUPPORT);
}
pn = malloc(sizeof(struct portalnode),
M_TEMP, M_WAITOK);
fmp = malloc(sizeof(struct portalmount),
M_PORTALFSMNT, M_WAITOK); /* XXX */
error = getnewvnode("portal", mp, &portal_vnodeops, &rvp); /* XXX */
if (error) {
free(fmp, M_PORTALFSMNT);
free(pn, M_TEMP);
fdrop(fp, td);
return (error);
}
error = insmntque(rvp, mp); /* XXX: Too early for mpsafe fs */
if (error != 0) {
free(fmp, M_PORTALFSMNT);
free(pn, M_TEMP);
fdrop(fp, td);
return (error);
}
rvp->v_data = pn;
rvp->v_type = VDIR;
rvp->v_vflag |= VV_ROOT;
VTOPORTAL(rvp)->pt_arg = 0;
VTOPORTAL(rvp)->pt_size = 0;
VTOPORTAL(rvp)->pt_fileid = PORTAL_ROOTFILEID;
fmp->pm_root = rvp;
fhold(fp);
fmp->pm_server = fp;
MNT_ILOCK(mp);
mp->mnt_flag |= MNT_LOCAL;
MNT_IUNLOCK(mp);
mp->mnt_data = fmp;
vfs_getnewfsid(mp);
vfs_mountedfrom(mp, p);
fdrop(fp, td);
return (0);
}
static int
portal_unmount(mp, mntflags)
struct mount *mp;
int mntflags;
{
int error, flags = 0;
if (mntflags & MNT_FORCE)
flags |= FORCECLOSE;
/*
* Clear out buffer cache. I don't think we
* ever get anything cached at this level at the
* moment, but who knows...
*/
#ifdef notyet
mntflushbuf(mp, 0);
if (mntinvalbuf(mp, 1))
return (EBUSY);
#endif
/* There is 1 extra root vnode reference (pm_root). */
error = vflush(mp, 1, flags, curthread);
if (error)
return (error);
/*
* Shutdown the socket. This will cause the select in the
* daemon to wake up, and then the accept will get ECONNABORTED
* which it interprets as a request to go and bury itself.
*/
soshutdown(VFSTOPORTAL(mp)->pm_server->f_data, 2);
/*
* Discard reference to underlying file. Must call closef because
* this may be the last reference.
*/
closef(VFSTOPORTAL(mp)->pm_server, (struct thread *) 0);
/*
* Finally, throw away the portalmount structure
*/
free(mp->mnt_data, M_PORTALFSMNT); /* XXX */
mp->mnt_data = NULL;
return (0);
}
static int
portal_root(mp, flags, vpp)
struct mount *mp;
int flags;
struct vnode **vpp;
{
struct vnode *vp;
/*
* Return locked reference to root.
*/
vp = VFSTOPORTAL(mp)->pm_root;
VREF(vp);
vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
*vpp = vp;
return (0);
}
static int
portal_statfs(mp, sbp)
struct mount *mp;
struct statfs *sbp;
{
sbp->f_flags = 0;
sbp->f_bsize = DEV_BSIZE;
sbp->f_iosize = DEV_BSIZE;
sbp->f_blocks = 2; /* 1K to keep df happy */
sbp->f_bfree = 0;
sbp->f_bavail = 0;
sbp->f_files = 1; /* Allow for "." */
sbp->f_ffree = 0; /* See comments above */
return (0);
}
static struct vfsops portal_vfsops = {
.vfs_cmount = portal_cmount,
.vfs_mount = portal_mount,
.vfs_root = portal_root,
.vfs_statfs = portal_statfs,
.vfs_unmount = portal_unmount,
};
VFS_SET(portal_vfsops, portalfs, VFCF_SYNTHETIC);

View File

@ -1,586 +0,0 @@
/*-
* Copyright (c) 1992, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software donated to Berkeley by
* Jan-Simon Pendry.
*
* 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.
* 4. Neither the name of the University 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 REGENTS 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 REGENTS 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.
*
* @(#)portal_vnops.c 8.14 (Berkeley) 5/21/95
*
* $FreeBSD$
*/
/*
* Portal Filesystem
*/
#include "opt_capsicum.h"
#include <sys/param.h>
#include <sys/capability.h>
#include <sys/fcntl.h>
#include <sys/file.h>
#include <sys/kernel.h>
#include <sys/lock.h>
#include <sys/malloc.h>
#include <sys/mbuf.h>
#include <sys/mount.h>
#include <sys/mutex.h>
#include <sys/namei.h>
#include <sys/proc.h>
#include <sys/socket.h>
#include <sys/socketvar.h>
#include <sys/stat.h>
#include <sys/syscallsubr.h>
#include <sys/systm.h>
#include <sys/un.h>
#include <sys/unpcb.h>
#include <sys/vnode.h>
#include <fs/portalfs/portal.h>
#include <net/vnet.h>
static int portal_fileid = PORTAL_ROOTFILEID+1;
static void portal_closefd(struct thread *td, int fd);
static int portal_connect(struct socket *so, struct socket *so2);
static vop_getattr_t portal_getattr;
static vop_lookup_t portal_lookup;
static vop_open_t portal_open;
static vop_readdir_t portal_readdir;
static vop_reclaim_t portal_reclaim;
static vop_setattr_t portal_setattr;
static void
portal_closefd(td, fd)
struct thread *td;
int fd;
{
int error;
error = kern_close(td, fd);
/*
* We should never get an error, and there isn't anything
* we could do if we got one, so just print a message.
*/
if (error)
printf("portal_closefd: error = %d\n", error);
}
/*
* vp is the current namei directory
* cnp is the name to locate in that directory...
*/
static int
portal_lookup(ap)
struct vop_lookup_args /* {
struct vnode * a_dvp;
struct vnode ** a_vpp;
struct componentname * a_cnp;
} */ *ap;
{
struct componentname *cnp = ap->a_cnp;
struct vnode **vpp = ap->a_vpp;
struct vnode *dvp = ap->a_dvp;
char *pname = cnp->cn_nameptr;
struct portalnode *pt;
int error;
struct vnode *fvp = NULL;
char *path;
int size;
*vpp = NULLVP;
if (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME)
return (EROFS);
if (cnp->cn_namelen == 1 && *pname == '.') {
*vpp = dvp;
VREF(dvp);
return (0);
}
KASSERT((cnp->cn_flags & ISDOTDOT) == 0,
("portal_lookup: Can not handle dotdot lookups."));
/*
* Do the MALLOC before the getnewvnode since doing so afterward
* might cause a bogus v_data pointer to get dereferenced
* elsewhere if MALLOC should block.
*/
pt = malloc(sizeof(struct portalnode),
M_TEMP, M_WAITOK);
error = getnewvnode("portal", dvp->v_mount, &portal_vnodeops, &fvp);
if (error) {
free(pt, M_TEMP);
goto bad;
}
fvp->v_type = VREG;
fvp->v_data = pt;
/*
* Save all of the remaining pathname and
* advance the namei next pointer to the end
* of the string.
*/
for (size = 0, path = pname; *path; path++)
size++;
cnp->cn_consume = size - cnp->cn_namelen;
pt->pt_arg = malloc(size+1, M_TEMP, M_WAITOK);
pt->pt_size = size+1;
bcopy(pname, pt->pt_arg, pt->pt_size);
pt->pt_fileid = portal_fileid++;
*vpp = fvp;
vn_lock(fvp, LK_EXCLUSIVE | LK_RETRY);
error = insmntque(fvp, dvp->v_mount);
if (error != 0) {
*vpp = NULLVP;
return (error);
}
return (0);
bad:;
if (fvp)
vrele(fvp);
return (error);
}
static int
portal_connect(so, so2)
struct socket *so;
struct socket *so2;
{
/* from unp_connect, bypassing the namei stuff... */
struct socket *so3;
struct unpcb *unp2;
struct unpcb *unp3;
if (so2 == 0)
return (ECONNREFUSED);
if (so->so_type != so2->so_type)
return (EPROTOTYPE);
if ((so2->so_options & SO_ACCEPTCONN) == 0)
return (ECONNREFUSED);
CURVNET_SET(so2->so_vnet);
if ((so3 = sonewconn(so2, 0)) == 0) {
CURVNET_RESTORE();
return (ECONNREFUSED);
}
CURVNET_RESTORE();
unp2 = sotounpcb(so2);
unp3 = sotounpcb(so3);
if (unp2->unp_addr)
unp3->unp_addr = (struct sockaddr_un *)
sodupsockaddr((struct sockaddr *)unp2->unp_addr,
M_NOWAIT);
so2 = so3;
return (soconnect2(so, so2));
}
static int
portal_open(ap)
struct vop_open_args /* {
struct vnode *a_vp;
int a_mode;
struct ucred *a_cred;
struct thread *a_td;
} */ *ap;
{
struct socket *so = NULL;
struct portalnode *pt;
struct thread *td = ap->a_td;
struct vnode *vp = ap->a_vp;
struct uio auio;
struct iovec aiov[2];
int res;
struct mbuf *cm = NULL;
struct cmsghdr *cmsg;
int newfds;
int *ip;
int fd;
int error;
int len;
struct portalmount *fmp;
struct file *fp;
struct portal_cred pcred;
#ifdef CAPABILITY_MODE
/*
* This may require access to a global namespace (e.g. an IP address);
* disallow it entirely, as we do open(2).
*/
if (IN_CAPABILITY_MODE(td)) {
#ifdef KTRACE
if (KTRPOINT(td, KTR_CAPFAIL))
ktrcapfail(CAPFAIL_SYSCALL, 0, 0);
#endif
return (ECAPMODE);
}
#endif
/*
* Nothing to do when opening the root node.
*/
if (vp->v_vflag & VV_ROOT)
return (0);
/*
* Can't be opened unless the caller is set up
* to deal with the side effects. Check for this
* by testing whether td_dupfd has been set.
*/
if (td->td_dupfd >= 0)
return (ENODEV);
pt = VTOPORTAL(vp);
fmp = VFSTOPORTAL(vp->v_mount);
/*
* Create a new socket.
*/
error = socreate(AF_UNIX, &so, SOCK_STREAM, 0, ap->a_cred,
ap->a_td);
if (error)
goto bad;
/*
* Reserve some buffer space
*/
res = pt->pt_size + sizeof(pcred) + 512; /* XXX */
error = soreserve(so, res, res);
if (error)
goto bad;
/*
* Kick off connection
*/
error = portal_connect(so, fmp->pm_server->f_data);
if (error)
goto bad;
/*
* Wait for connection to complete
*/
/*
* XXX: Since the mount point is holding a reference on the
* underlying server socket, it is not easy to find out whether
* the server process is still running. To handle this problem
* we loop waiting for the new socket to be connected (something
* which will only happen if the server is still running) or for
* the reference count on the server socket to drop to 1, which
* will happen if the server dies. Sleep for 5 second intervals
* and keep polling the reference count. XXX.
*/
SOCK_LOCK(so);
while ((so->so_state & SS_ISCONNECTING) && so->so_error == 0) {
if (fmp->pm_server->f_count == 1) {
SOCK_UNLOCK(so);
error = ECONNREFUSED;
goto bad;
}
(void) msleep((caddr_t) &so->so_timeo, SOCK_MTX(so), PSOCK,
"portalcon", 5 * hz);
}
SOCK_UNLOCK(so);
if (so->so_error) {
error = so->so_error;
goto bad;
}
/*
* Set miscellaneous flags
*/
SOCKBUF_LOCK(&so->so_rcv);
so->so_rcv.sb_timeo = 0;
so->so_rcv.sb_flags |= SB_NOINTR;
SOCKBUF_UNLOCK(&so->so_rcv);
SOCKBUF_LOCK(&so->so_snd);
so->so_snd.sb_timeo = 0;
so->so_snd.sb_flags |= SB_NOINTR;
SOCKBUF_UNLOCK(&so->so_snd);
pcred.pcr_flag = ap->a_mode;
pcred.pcr_uid = ap->a_cred->cr_uid;
pcred.pcr_ngroups = MIN(ap->a_cred->cr_ngroups, XU_NGROUPS);
bcopy(ap->a_cred->cr_groups, pcred.pcr_groups,
pcred.pcr_ngroups * sizeof(gid_t));
aiov[0].iov_base = (caddr_t) &pcred;
aiov[0].iov_len = sizeof(pcred);
aiov[1].iov_base = pt->pt_arg;
aiov[1].iov_len = pt->pt_size;
auio.uio_iov = aiov;
auio.uio_iovcnt = 2;
auio.uio_rw = UIO_WRITE;
auio.uio_segflg = UIO_SYSSPACE;
auio.uio_td = td;
auio.uio_offset = 0;
auio.uio_resid = aiov[0].iov_len + aiov[1].iov_len;
error = sosend(so, (struct sockaddr *) 0, &auio,
(struct mbuf *) 0, (struct mbuf *) 0, 0 , td);
if (error)
goto bad;
len = auio.uio_resid = sizeof(int);
do {
struct mbuf *m = NULL;
int flags = MSG_WAITALL;
error = soreceive(so, (struct sockaddr **) 0, &auio,
&m, &cm, &flags);
if (error)
goto bad;
/*
* Grab an error code from the mbuf.
*/
if (m) {
m = m_pullup(m, sizeof(int)); /* Needed? */
if (m) {
error = *(mtod(m, int *));
m_freem(m);
} else {
error = EINVAL;
}
} else {
if (cm == 0) {
error = ECONNRESET; /* XXX */
#ifdef notdef
break;
#endif
}
}
} while (cm == 0 && auio.uio_resid == len && !error);
if (cm == 0)
goto bad;
if (auio.uio_resid) {
error = 0;
#ifdef notdef
error = EMSGSIZE;
goto bad;
#endif
}
/*
* XXX: Break apart the control message, and retrieve the
* received file descriptor. Note that more than one descriptor
* may have been received, or that the rights chain may have more
* than a single mbuf in it. What to do?
*/
cmsg = mtod(cm, struct cmsghdr *);
newfds = (cmsg->cmsg_len - sizeof(*cmsg)) / sizeof (int);
if (newfds == 0) {
error = ECONNREFUSED;
goto bad;
}
/*
* At this point the rights message consists of a control message
* header, followed by a data region containing a vector of
* integer file descriptors. The fds were allocated by the action
* of receiving the control message.
*/
ip = (int *) (cmsg + 1);
fd = *ip++;
if (newfds > 1) {
/*
* Close extra fds.
*/
int i;
printf("portal_open: %d extra fds\n", newfds - 1);
for (i = 1; i < newfds; i++) {
portal_closefd(td, *ip);
ip++;
}
}
/*
* Check that the mode the file is being opened for is a subset
* of the mode of the existing descriptor.
*/
if ((error = fget(td, fd, 0, &fp)) != 0)
goto bad;
if (((ap->a_mode & (FREAD|FWRITE)) | fp->f_flag) != fp->f_flag) {
fdrop(fp, td);
portal_closefd(td, fd);
error = EACCES;
goto bad;
}
fdrop(fp, td);
/*
* Save the dup fd in the proc structure then return the
* special error code (ENXIO) which causes magic things to
* happen in vn_open. The whole concept is, well, hmmm.
*/
td->td_dupfd = fd;
error = ENXIO;
bad:;
/*
* And discard the control message.
*/
if (cm) {
m_freem(cm);
}
if (so) {
soshutdown(so, 2);
soclose(so);
}
return (error);
}
static int
portal_getattr(ap)
struct vop_getattr_args /* {
struct vnode *a_vp;
struct vattr *a_vap;
struct ucred *a_cred;
} */ *ap;
{
struct vnode *vp = ap->a_vp;
struct vattr *vap = ap->a_vap;
vap->va_uid = 0;
vap->va_gid = 0;
vap->va_size = DEV_BSIZE;
vap->va_blocksize = DEV_BSIZE;
nanotime(&vap->va_atime);
vap->va_mtime = vap->va_atime;
vap->va_ctime = vap->va_mtime;
vap->va_gen = 0;
vap->va_flags = 0;
vap->va_rdev = NODEV;
/* vap->va_qbytes = 0; */
vap->va_bytes = 0;
vap->va_filerev = 0;
/* vap->va_qsize = 0; */
if (vp->v_vflag & VV_ROOT) {
vap->va_type = VDIR;
vap->va_mode = S_IRUSR|S_IWUSR|S_IXUSR|
S_IRGRP|S_IWGRP|S_IXGRP|
S_IROTH|S_IWOTH|S_IXOTH;
vap->va_nlink = 2;
vap->va_fileid = 2;
} else {
vap->va_type = VREG;
vap->va_mode = S_IRUSR|S_IWUSR|
S_IRGRP|S_IWGRP|
S_IROTH|S_IWOTH;
vap->va_nlink = 1;
vap->va_fileid = VTOPORTAL(vp)->pt_fileid;
}
return (0);
}
static int
portal_setattr(ap)
struct vop_setattr_args /* {
struct vnode *a_vp;
struct vattr *a_vap;
struct ucred *a_cred;
} */ *ap;
{
/*
* Can't mess with the root vnode
*/
if (ap->a_vp->v_vflag & VV_ROOT)
return (EACCES);
if (ap->a_vap->va_flags != VNOVAL)
return (EOPNOTSUPP);
return (0);
}
/*
* Fake readdir, just return empty directory.
* It is hard to deal with '.' and '..' so don't bother.
*/
static int
portal_readdir(ap)
struct vop_readdir_args /* {
struct vnode *a_vp;
struct uio *a_uio;
struct ucred *a_cred;
int *a_eofflag;
u_long *a_cookies;
int a_ncookies;
} */ *ap;
{
/*
* We don't allow exporting portal mounts, and currently local
* requests do not need cookies.
*/
if (ap->a_ncookies)
panic("portal_readdir: not hungry");
return (0);
}
static int
portal_reclaim(ap)
struct vop_reclaim_args /* {
struct vnode *a_vp;
} */ *ap;
{
struct portalnode *pt = VTOPORTAL(ap->a_vp);
if (pt->pt_arg) {
free((caddr_t) pt->pt_arg, M_TEMP);
pt->pt_arg = 0;
}
free(ap->a_vp->v_data, M_TEMP);
ap->a_vp->v_data = 0;
return (0);
}
struct vop_vector portal_vnodeops = {
.vop_default = &default_vnodeops,
.vop_access = VOP_NULL,
.vop_getattr = portal_getattr,
.vop_lookup = portal_lookup,
.vop_open = portal_open,
.vop_pathconf = vop_stdpathconf,
.vop_readdir = portal_readdir,
.vop_reclaim = portal_reclaim,
.vop_setattr = portal_setattr,
};

View File

@ -32,21 +32,72 @@ __FBSDID("$FreeBSD$");
#include <sys/kernel.h>
#include <sys/malloc.h>
#include <fs/ntfs/ntfs.h>
#include <geom/geom.h>
#include <geom/label/g_label.h>
#define NTFS_A_VOLUMENAME 0x60
#define NTFS_FILEMAGIC ((uint32_t)(0x454C4946))
#define NTFS_VOLUMEINO 3
#define G_LABEL_NTFS_DIR "ntfs"
struct ntfs_attr {
uint32_t a_type;
uint32_t reclen;
uint8_t a_flag;
uint8_t a_namelen;
uint8_t a_nameoff;
uint8_t reserved1;
uint8_t a_compression;
uint8_t reserved2;
uint16_t a_index;
uint16_t a_datalen;
uint16_t reserved3;
uint16_t a_dataoff;
uint16_t a_indexed;
};
struct ntfs_filerec {
uint32_t fr_hdrmagic;
uint16_t fr_hdrfoff;
uint16_t fr_hdrfnum;
uint8_t reserved[8];
uint16_t fr_seqnum;
uint16_t fr_nlink;
uint16_t fr_attroff;
uint16_t fr_flags;
uint32_t fr_size;
uint32_t fr_allocated;
uint64_t fr_mainrec;
uint16_t fr_attrnum;
};
struct ntfs_bootfile {
uint8_t reserved1[3];
uint8_t bf_sysid[8];
uint16_t bf_bps;
uint8_t bf_spc;
uint8_t reserved2[7];
uint8_t bf_media;
uint8_t reserved3[2];
uint16_t bf_spt;
uint16_t bf_heads;
uint8_t reserver4[12];
uint64_t bf_spv;
uint64_t bf_mftcn;
uint64_t bf_mftmirrcn;
uint8_t bf_mftrecsz;
uint32_t bf_ibsz;
uint32_t bf_volsn;
};
static void
g_label_ntfs_taste(struct g_consumer *cp, char *label, size_t size)
{
struct g_provider *pp;
struct bootfile *bf;
struct filerec *fr;
struct attr *atr;
struct ntfs_bootfile *bf;
struct ntfs_filerec *fr;
struct ntfs_attr *atr;
off_t voloff;
char *filerecp, *ap;
char mftrecsz, vnchar;
@ -58,7 +109,7 @@ g_label_ntfs_taste(struct g_consumer *cp, char *label, size_t size)
pp = cp->provider;
filerecp = NULL;
bf = (struct bootfile *)g_read_data(cp, 0, pp->sectorsize, NULL);
bf = (struct ntfs_bootfile *)g_read_data(cp, 0, pp->sectorsize, NULL);
if (bf == NULL || strncmp(bf->bf_sysid, "NTFS ", 8) != 0)
goto done;
@ -75,16 +126,16 @@ g_label_ntfs_taste(struct g_consumer *cp, char *label, size_t size)
filerecp = g_read_data(cp, voloff, recsize, NULL);
if (filerecp == NULL)
goto done;
fr = (struct filerec *)filerecp;
fr = (struct ntfs_filerec *)filerecp;
if (fr->fr_fixup.fh_magic != NTFS_FILEMAGIC)
if (fr->fr_hdrmagic != NTFS_FILEMAGIC)
goto done;
for (ap = filerecp + fr->fr_attroff;
atr = (struct attr *)ap, atr->a_hdr.a_type != -1;
ap += atr->a_hdr.reclen) {
if (atr->a_hdr.a_type == NTFS_A_VOLUMENAME) {
if(atr->a_r.a_datalen >= size *2){
atr = (struct ntfs_attr *)ap, atr->a_type != -1;
ap += atr->reclen) {
if (atr->a_type == NTFS_A_VOLUMENAME) {
if(atr->a_datalen >= size *2){
label[0] = 0;
goto done;
}
@ -92,8 +143,8 @@ g_label_ntfs_taste(struct g_consumer *cp, char *label, size_t size)
*UNICODE to ASCII.
* Should we need to use iconv(9)?
*/
for (j = 0; j < atr->a_r.a_datalen; j++) {
vnchar = *(ap + atr->a_r.a_dataoff + j);
for (j = 0; j < atr->a_datalen; j++) {
vnchar = *(ap + atr->a_dataoff + j);
if (j & 1) {
if (vnchar) {
label[0] = 0;

View File

@ -1,36 +0,0 @@
#ifndef __XFS_SUPPORT_ATOMIC_H__
#include <sys/types.h>
#include <machine/atomic.h>
typedef struct {
volatile unsigned int val;
} atomic_t;
#define atomic_read(v) ((v)->val)
#define atomic_set(v, i) ((v)->val = (i))
#define atomic_add(i, v) atomic_add_int(&(v)->val, (i))
#define atomic_inc(v) atomic_add_int(&(v)->val, 1)
#define atomic_dec(v) atomic_subtract_int(&(v)->val, 1)
#define atomic_sub(i, v) atomic_subtract_int(&(v)->val, (i))
#define atomic_dec_and_test(v) (atomic_fetchadd_int(&(v)->val, -1) == 1)
/*
* This is used for two variables in XFS, one of which is a debug trace
* buffer index.
*/
static __inline__ int atomicIncWithWrap(volatile unsigned int *ip, int val)
{
unsigned int oldval, newval;
do {
oldval = *ip;
newval = (oldval + 1 >= val) ? 0 : oldval + 1;
} while (atomic_cmpset_rel_int(ip, oldval, newval) == 0);
return oldval;
}
#endif /* __XFS_SUPPORT_ATOMIC_H__ */

View File

@ -1,97 +0,0 @@
/*
* Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it would be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*
* Further, this software is distributed without any warranty that it is
* free of the rightful claim of any third person regarding infringement
* or the like. Any license provided herein, whether implied or
* otherwise, applies only to this software file. Patent licenses, if
* any, provided herein do not apply to combinations of this program with
* other software, or any other product whatsoever.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write the Free Software Foundation, Inc., 59
* Temple Place - Suite 330, Boston MA 02111-1307, USA.
*
* Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
* Mountain View, CA 94043, or:
*
* http://www.sgi.com
*
* For further information regarding this notice, see:
*
* http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
*/
#include <sys/param.h>
#include <sys/proc.h>
#include <sys/kernel.h>
#include <sys/systm.h>
#include <sys/sysctl.h>
#include <machine/stdarg.h>
#include <support/debug.h>
static SYSCTL_NODE(_debug, OID_AUTO, xfs, CTLFLAG_RD, 0, "XFS debug options");
static int verbosity = 10;
SYSCTL_INT(_debug_xfs, OID_AUTO, verbosity, CTLFLAG_RW, &verbosity, 0, "");
#ifdef DEBUG
static int doass = 1;
SYSCTL_INT(_debug_xfs, OID_AUTO, assert, CTLFLAG_RW, &doass, 0, "");
void
assfail(char *a, char *f, int l)
{
if (doass == 0) return;
panic("XFS assertion failed: %s, file: %s, line: %d\n", a, f, l);
}
int
get_thread_id(void)
{
return curthread->td_proc->p_pid;
}
#endif
void
cmn_err(register int level, char *fmt, ...)
{
char *fp = fmt;
char message[256];
va_list ap;
if (verbosity < level)
return;
va_start(ap, fmt);
if (*fmt == '!') fp++;
vsprintf(message, fp, ap);
printf("%s\n", message);
va_end(ap);
}
void
icmn_err(register int level, char *fmt, va_list ap)
{
char message[256];
if (verbosity < level)
return;
vsprintf(message, fmt, ap);
printf("cmn_err level %d %s\n",level, message);
}

View File

@ -1,79 +0,0 @@
/*
* Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it would be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*
* Further, this software is distributed without any warranty that it is
* free of the rightful claim of any third person regarding infringement
* or the like. Any license provided herein, whether implied or
* otherwise, applies only to this software file. Patent licenses, if
* any, provided herein do not apply to combinations of this program with
* other software, or any other product whatsoever.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write the Free Software Foundation, Inc., 59
* Temple Place - Suite 330, Boston MA 02111-1307, USA.
*
* Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
* Mountain View, CA 94043, or:
*
* http://www.sgi.com
*
* For further information regarding this notice, see:
*
* http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
*/
#ifndef __XFS_SUPPORT_DEBUG_H__
#define __XFS_SUPPORT_DEBUG_H__
#include <machine/stdarg.h>
#define CE_DEBUG 7 /* debug */
#define CE_CONT 6 /* continuation */
#define CE_NOTE 5 /* notice */
#define CE_WARN 4 /* warning */
#define CE_ALERT 1 /* alert */
#define CE_PANIC 0 /* panic */
extern void icmn_err(int, char *, va_list);
extern void cmn_err(int, char *, ...);
#define prdev(fmt,targ,args...) \
printf("Device %s - " fmt "\n", XFS_BUFTARG_NAME(targ), ## args)
#ifndef STATIC
# define STATIC static
#endif
#if defined(INVARIANTS)
# ifndef DEBUG
# define DEBUG
# endif
#endif
#if defined(DEBUG)
# ifdef lint
# define ASSERT(EX) ((void)0) /* avoid "constant in conditional" babble */
# else
# define ASSERT(EX) ((EX)?((void)0):assfail(#EX, __FILE__, __LINE__))
# endif /* lint */
#else /* !DEBUG */
# define ASSERT(x) ((void)0)
#endif /* !DEBUG */
#ifdef DEBUG
extern void assfail(char *, char *, int);
extern int get_thread_id(void);
#else
#define assfail(a, b, c) ((void)0)
#endif
#define ASSERT_ALWAYS(EX) ((EX)?((void)0):assfail(#EX, __FILE__, __LINE__))
#endif /* __XFS_SUPPORT_DEBUG_H__ */

View File

@ -1,62 +0,0 @@
#include <sys/param.h>
#include <sys/kernel.h>
#include <sys/systm.h>
#include <machine/db_machdep.h>
#include "opt_ddb.h"
#ifdef DDB
#include <ddb/ddb.h>
#endif
#include <support/kdb.h>
#ifdef DDB
DB_FUNC(xfs, xfs_ddb_cmd, db_cmd_table, CS_MORE, NULL)
{
db_error("No commands registered.\n");
}
#endif
int
kdb_register(char *cmd, kdb_func_t func, char *usage, char *help, short minlen)
{
return 0;
}
int
kdb_unregister(char *cmd)
{
return 0;
}
int
kdbgetaddrarg(int argc, const char **argv, int *nextarg,
kdb_machreg_t *value, long *offset, char **name, struct pt_regs *regs)
{
return 0;
}
int
kdbnearsym(unsigned long addr, kdb_symtab_t *symtab)
{
return 0;
}
void
kdb_printf(const char *fmt, ...)
{
}
int
kdb_getarea_size(void *res, unsigned long addr, size_t size)
{
return 0;
}
int
kdb_putarea_size(unsigned long addr, void *res, size_t size)
{
return 0;
}

View File

@ -1,44 +0,0 @@
#ifndef __XFS_SUPPORT_KGDB_H__
#define __XFS_SUPPORT_KGDB_H__
#define KDB_ARGCOUNT EINVAL
struct pt_regs
{
int dummy;
};
#define MODULE_AUTHOR(s) static char __module_author[] = s;
#define MODULE_DESCRIPTION(s) static char __module_description[] = s;
#define MODULE_LICENSE(s) static char __module_license[] = s
typedef int (*kdb_func_t)(int, const char **, const char **, struct pt_regs *);
typedef register_t kdb_machreg_t;
/*
* Symbol table format.
*/
typedef struct __ksymtab {
unsigned long value; /* Address of symbol */
const char *sym_name; /* Full symbol name, including any version */
unsigned long sym_start;
unsigned long sym_end;
} kdb_symtab_t;
extern int kdb_register(char *, kdb_func_t, char *, char *, short);
extern int kdb_unregister(char *);
extern int kdbgetaddrarg(int, const char**, int*, kdb_machreg_t *,
long *, char **, struct pt_regs *);
extern int kdbnearsym(unsigned long, kdb_symtab_t *);
extern void kdb_printf(const char *,...)
__attribute__ ((format (printf, 1, 2)));
extern int kdb_getarea_size(void *, unsigned long, size_t);
extern int kdb_putarea_size(unsigned long, void *, size_t);
#define kdb_getarea(x,addr) kdb_getarea_size(&(x), addr, sizeof((x)))
#define kdb_putarea(addr,x) kdb_putarea_size(addr, &(x), sizeof((x)))
#endif /* __XFS_SUPPORT_KGDB_H__ */

View File

@ -1,3 +0,0 @@
#include <support/kmem.h>
MALLOC_DEFINE(M_XFS, "XFSALLOC", "XFS memory");

View File

@ -1,86 +0,0 @@
#ifndef __XFS_SUPPORT_KMEM_H__
#define __XFS_SUPPORT_KMEM_H__
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/malloc.h>
#include <sys/kernel.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <vm/uma.h>
typedef unsigned long xfs_pflags_t;
#define PFLAGS_TEST_NOIO() 0
#define PFLAGS_TEST_FSTRANS() 0
#define PFLAGS_SET_NOIO(STATEP) do { \
} while (0)
#define PFLAGS_SET_FSTRANS(STATEP) do { \
} while (0)
#define PFLAGS_RESTORE(STATEP) do { \
} while (0)
#define PFLAGS_DUP(OSTATEP, NSTATEP) do { \
} while (0)
/* Restore the PF_FSTRANS state to what was saved in STATEP */
#define PFLAGS_RESTORE_FSTRANS(STATEP) do { \
} while (0)
/*
* memory management routines
*/
#define KM_SLEEP M_WAITOK
#define KM_NOSLEEP M_NOWAIT
#define KM_NOFS M_WAITOK
#define KM_MAYFAIL 0
#define kmem_zone uma_zone
typedef struct uma_zone kmem_zone_t;
typedef struct uma_zone xfs_zone_t;
#define KM_ZONE_HWALIGN 0
#define KM_ZONE_RECLAIM 0
#define KM_ZONE_SPREAD 0
#define kmem_zone_init(len, name) \
uma_zcreate(name, len, NULL, NULL, NULL, NULL, 0, 0)
static inline kmem_zone_t *
kmem_zone_init_flags(int size, char *zone_name, unsigned long flags,
void (*construct)(void *, kmem_zone_t *, unsigned long))
{
return uma_zcreate(zone_name, size, NULL, NULL, NULL, NULL, 0, 0);
}
#define kmem_zone_free(zone, ptr) \
uma_zfree(zone, ptr)
static inline void
kmem_zone_destroy(kmem_zone_t *zone)
{
uma_zdestroy(zone);
}
#define kmem_zone_alloc(zone, flg) \
uma_zalloc(zone, flg)
#define kmem_zone_zalloc(zone, flg) \
uma_zalloc(zone, (flg) | M_ZERO)
#define kmem_alloc(len, flg) \
malloc(len, M_XFS, flg)
#define kmem_zalloc(len, flg) \
malloc(len, M_XFS, (flg) | M_ZERO)
#define kmem_free(ptr, size) \
free(ptr, M_XFS)
#define kmem_realloc(ptr, nsize, osize, flg) \
realloc(ptr, nsize, M_XFS, flg)
MALLOC_DECLARE(M_XFS);
#endif /* __XFS_SUPPORT_KMEM_H__ */

View File

@ -1,334 +0,0 @@
/*
* Copyright (c) 2000-2003,2005 Silicon Graphics, Inc.
* All Rights Reserved.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it would be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <xfs.h>
static kmem_zone_t *ktrace_hdr_zone;
static kmem_zone_t *ktrace_ent_zone;
static int ktrace_zentries;
static struct mtx wrap_lock;
void
ktrace_init(int zentries)
{
ktrace_zentries = zentries;
ktrace_hdr_zone = kmem_zone_init(sizeof(ktrace_t),
"ktrace_hdr");
ASSERT(ktrace_hdr_zone);
ktrace_ent_zone = kmem_zone_init(ktrace_zentries
* sizeof(ktrace_entry_t),
"ktrace_ent");
ASSERT(ktrace_ent_zone);
mtx_init(&wrap_lock, "xfsktr", NULL, MTX_DEF);
}
void
ktrace_uninit(void)
{
kmem_zone_destroy(ktrace_hdr_zone);
kmem_zone_destroy(ktrace_ent_zone);
mtx_destroy(&wrap_lock);
}
/*
* ktrace_alloc()
*
* Allocate a ktrace header and enough buffering for the given
* number of entries.
*/
ktrace_t *
ktrace_alloc(int nentries, int sleep)
{
ktrace_t *ktp;
ktrace_entry_t *ktep;
ktp = (ktrace_t*)kmem_zone_alloc(ktrace_hdr_zone, sleep);
if (ktp == (ktrace_t*)NULL) {
/*
* KM_SLEEP callers don't expect failure.
*/
if (sleep & KM_SLEEP)
panic("ktrace_alloc: NULL memory on KM_SLEEP request!");
return NULL;
}
/*
* Special treatment for buffers with the ktrace_zentries entries
*/
if (nentries == ktrace_zentries) {
ktep = (ktrace_entry_t*)kmem_zone_zalloc(ktrace_ent_zone,
sleep);
} else {
ktep = (ktrace_entry_t*)kmem_zalloc((nentries * sizeof(*ktep)),
sleep);
}
if (ktep == NULL) {
/*
* KM_SLEEP callers don't expect failure.
*/
if (sleep & KM_SLEEP)
panic("ktrace_alloc: NULL memory on KM_SLEEP request!");
kmem_free(ktp, sizeof(*ktp));
return NULL;
}
spinlock_init(&(ktp->kt_lock), "kt_lock");
ktp->kt_entries = ktep;
ktp->kt_nentries = nentries;
ktp->kt_index = 0;
ktp->kt_rollover = 0;
return ktp;
}
/*
* ktrace_free()
*
* Free up the ktrace header and buffer. It is up to the caller
* to ensure that no-one is referencing it.
*/
void
ktrace_free(ktrace_t *ktp)
{
int entries_size;
if (ktp == (ktrace_t *)NULL)
return;
spinlock_destroy(&ktp->kt_lock);
/*
* Special treatment for the Vnode trace buffer.
*/
if (ktp->kt_nentries == ktrace_zentries) {
kmem_zone_free(ktrace_ent_zone, ktp->kt_entries);
} else {
entries_size = (int)(ktp->kt_nentries * sizeof(ktrace_entry_t));
kmem_free(ktp->kt_entries, entries_size);
}
kmem_zone_free(ktrace_hdr_zone, ktp);
}
/*
* Enter the given values into the "next" entry in the trace buffer.
* kt_index is always the index of the next entry to be filled.
*/
void
ktrace_enter(
ktrace_t *ktp,
void *val0,
void *val1,
void *val2,
void *val3,
void *val4,
void *val5,
void *val6,
void *val7,
void *val8,
void *val9,
void *val10,
void *val11,
void *val12,
void *val13,
void *val14,
void *val15)
{
int index;
ktrace_entry_t *ktep;
ASSERT(ktp != NULL);
/*
* Grab an entry by pushing the index up to the next one.
*/
mtx_lock(&wrap_lock);
index = ktp->kt_index;
if (++ktp->kt_index == ktp->kt_nentries)
ktp->kt_index = 0;
mtx_unlock(&wrap_lock);
if (!ktp->kt_rollover && index == ktp->kt_nentries - 1)
ktp->kt_rollover = 1;
ASSERT((index >= 0) && (index < ktp->kt_nentries));
ktep = &(ktp->kt_entries[index]);
ktep->val[0] = val0;
ktep->val[1] = val1;
ktep->val[2] = val2;
ktep->val[3] = val3;
ktep->val[4] = val4;
ktep->val[5] = val5;
ktep->val[6] = val6;
ktep->val[7] = val7;
ktep->val[8] = val8;
ktep->val[9] = val9;
ktep->val[10] = val10;
ktep->val[11] = val11;
ktep->val[12] = val12;
ktep->val[13] = val13;
ktep->val[14] = val14;
ktep->val[15] = val15;
}
/*
* Return the number of entries in the trace buffer.
*/
int
ktrace_nentries(
ktrace_t *ktp)
{
if (ktp == NULL) {
return 0;
}
return (ktp->kt_rollover ? ktp->kt_nentries : ktp->kt_index);
}
/*
* ktrace_first()
*
* This is used to find the start of the trace buffer.
* In conjunction with ktrace_next() it can be used to
* iterate through the entire trace buffer. This code does
* not do any locking because it is assumed that it is called
* from the debugger.
*
* The caller must pass in a pointer to a ktrace_snap
* structure in which we will keep some state used to
* iterate through the buffer. This state must not touched
* by any code outside of this module.
*/
ktrace_entry_t *
ktrace_first(ktrace_t *ktp, ktrace_snap_t *ktsp)
{
ktrace_entry_t *ktep;
int index;
int nentries;
if (ktp->kt_rollover)
index = ktp->kt_index;
else
index = 0;
ktsp->ks_start = index;
ktep = &(ktp->kt_entries[index]);
nentries = ktrace_nentries(ktp);
index++;
if (index < nentries) {
ktsp->ks_index = index;
} else {
ktsp->ks_index = 0;
if (index > nentries)
ktep = NULL;
}
return ktep;
}
/*
* ktrace_next()
*
* This is used to iterate through the entries of the given
* trace buffer. The caller must pass in the ktrace_snap_t
* structure initialized by ktrace_first(). The return value
* will be either a pointer to the next ktrace_entry or NULL
* if all of the entries have been traversed.
*/
ktrace_entry_t *
ktrace_next(
ktrace_t *ktp,
ktrace_snap_t *ktsp)
{
int index;
ktrace_entry_t *ktep;
index = ktsp->ks_index;
if (index == ktsp->ks_start) {
ktep = NULL;
} else {
ktep = &ktp->kt_entries[index];
}
index++;
if (index == ktrace_nentries(ktp)) {
ktsp->ks_index = 0;
} else {
ktsp->ks_index = index;
}
return ktep;
}
/*
* ktrace_skip()
*
* Skip the next "count" entries and return the entry after that.
* Return NULL if this causes us to iterate past the beginning again.
*/
ktrace_entry_t *
ktrace_skip(
ktrace_t *ktp,
int count,
ktrace_snap_t *ktsp)
{
int index;
int new_index;
ktrace_entry_t *ktep;
int nentries = ktrace_nentries(ktp);
index = ktsp->ks_index;
new_index = index + count;
while (new_index >= nentries) {
new_index -= nentries;
}
if (index == ktsp->ks_start) {
/*
* We've iterated around to the start, so we're done.
*/
ktep = NULL;
} else if ((new_index < index) && (index < ktsp->ks_index)) {
/*
* We've skipped past the start again, so we're done.
*/
ktep = NULL;
ktsp->ks_index = ktsp->ks_start;
} else {
ktep = &(ktp->kt_entries[new_index]);
new_index++;
if (new_index == nentries) {
ktsp->ks_index = 0;
} else {
ktsp->ks_index = new_index;
}
}
return ktep;
}

View File

@ -1,101 +0,0 @@
/*
* Copyright (c) 2000-2003 Silicon Graphics, Inc. All Rights Reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it would be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*
* Further, this software is distributed without any warranty that it is
* free of the rightful claim of any third person regarding infringement
* or the like. Any license provided herein, whether implied or
* otherwise, applies only to this software file. Patent licenses, if
* any, provided herein do not apply to combinations of this program with
* other software, or any other product whatsoever.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write the Free Software Foundation, Inc., 59
* Temple Place - Suite 330, Boston MA 02111-1307, USA.
*
* Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
* Mountain View, CA 94043, or:
*
* http://www.sgi.com
*
* For further information regarding this notice, see:
*
* http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
*/
#ifndef __XFS_SUPPORT_KTRACE_H__
#define __XFS_SUPPORT_KTRACE_H__
#include <support/spin.h>
/*
* Trace buffer entry structure.
*/
typedef struct ktrace_entry {
void *val[16];
} ktrace_entry_t;
/*
* Trace buffer header structure.
*/
typedef struct ktrace {
lock_t kt_lock; /* mutex to guard counters */
int kt_nentries; /* number of entries in trace buf */
int kt_index; /* current index in entries */
int kt_rollover;
ktrace_entry_t *kt_entries; /* buffer of entries */
} ktrace_t;
/*
* Trace buffer snapshot structure.
*/
typedef struct ktrace_snap {
int ks_start; /* kt_index at time of snap */
int ks_index; /* current index */
} ktrace_snap_t;
#ifdef CONFIG_XFS_TRACE
extern void ktrace_init(int zentries);
extern void ktrace_uninit(void);
extern ktrace_t *ktrace_alloc(int, int);
extern void ktrace_free(ktrace_t *);
extern void ktrace_enter(
ktrace_t *,
void *,
void *,
void *,
void *,
void *,
void *,
void *,
void *,
void *,
void *,
void *,
void *,
void *,
void *,
void *,
void *);
extern ktrace_entry_t *ktrace_first(ktrace_t *, ktrace_snap_t *);
extern int ktrace_nentries(ktrace_t *);
extern ktrace_entry_t *ktrace_next(ktrace_t *, ktrace_snap_t *);
extern ktrace_entry_t *ktrace_skip(ktrace_t *, int, ktrace_snap_t *);
#else
#define ktrace_init(x) do { } while (0)
#define ktrace_uninit() do { } while (0)
#endif /* CONFIG_XFS_TRACE */
#endif /* __XFS_SUPPORT_KTRACE_H__ */

View File

@ -1,48 +0,0 @@
/*
* Copyright (c) 2000-2002 Silicon Graphics, Inc. All Rights Reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it would be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*
* Further, this software is distributed without any warranty that it is
* free of the rightful claim of any third person regarding infringement
* or the like. Any license provided herein, whether implied or
* otherwise, applies only to this software file. Patent licenses, if
* any, provided herein do not apply to combinations of this program with
* other software, or any other product whatsoever.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write the Free Software Foundation, Inc., 59
* Temple Place - Suite 330, Boston MA 02111-1307, USA.
*
* Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
* Mountain View, CA 94043, or:
*
* http://www.sgi.com
*
* For further information regarding this notice, see:
*
* http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
*/
#ifndef __XFS_SUPPORT_MOVE_H__
#define __XFS_SUPPORT_MOVE_H__
#include <sys/uio.h>
typedef struct iovec iovec_t;
typedef struct uio uio_t;
static __inline__ int
uio_read(void *buf, int howmuch, struct uio *uiop)
{
uiop->uio_rw = UIO_READ;
return uiomove(buf,howmuch,uiop);
}
#endif /* __XFS_SUPPORT_MOVE_H__ */

View File

@ -1,14 +0,0 @@
#include <sys/param.h>
#include <sys/pcpu.h>
#include <support/debug.h>
#include <support/mrlock.h>
int
ismrlocked(mrlock_t *mrp, int type)
{
sx_assert(mrp, SX_LOCKED);
if (type == MR_UPDATE)
return sx_xlocked(mrp);
return 1;
}

View File

@ -1,41 +0,0 @@
#ifndef __XFS_SUPPORT_MRLOCK_H__
#define __XFS_SUPPORT_MRLOCK_H__
#include <sys/types.h>
#include <sys/systm.h>
#include <sys/lock.h>
#include <sys/sx.h>
/*
* Implement mrlocks on FreeBSD that work for XFS.
* Map mrlock functions to corresponding equivalents in
* sx.
*/
typedef struct sx mrlock_t;
#define MR_ACCESS 1
#define MR_UPDATE 2
/*
* Compatibility defines, not really used
*/
#define MRLOCK_BARRIER 0x1
#define MRLOCK_ALLOW_EQUAL_PRI 0x8
#define mrlock_init(lock, type, name, seq) sx_init(lock, name)
#define mrtryaccess(lock) sx_try_slock(lock)
#define mrtryupdate(lock) sx_try_xlock(lock)
#define mraccess(lock) sx_slock(lock)
#define mrupdate(lock) sx_xlock(lock)
#define mrdemote(lock) sx_downgrade(lock)
#define mrunlock(lock) sx_unlock(lock)
#define mrfree(lock) do { \
if (sx_xlocked(lock)) \
sx_xunlock(lock); \
sx_destroy(lock); \
} while (0)
int ismrlocked(mrlock_t *mrp, int type);
#endif /* __XFS_SUPPORT_MRLOCK_H__ */

View File

@ -1,29 +0,0 @@
#ifndef __XFS_SUPPORT_MUTEX_H__
#define __XFS_SUPPORT_MUTEX_H__
#include <sys/param.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/sx.h>
/*
* Map the mutex'es from IRIX to FreeBSD. Irix holds mutexes across
* sleeps, so on FreeBSD we have a choice of sema, sx or lockmgr
* to use as a underlining implemenation. Go with sx always locked
* in exclusive mode for now as it gets all the benefits of witness
* checking.
*/
typedef struct sx mutex_t;
#define mutex_init(lock, type, name) sx_init(lock, name)
#define mutex_lock(lock, num) sx_xlock(lock)
#define mutex_trylock(lock) sx_try_xlock(lock)
#define mutex_unlock(lock) sx_xunlock(lock)
#define mutex_destroy(lock) sx_destroy(lock)
/*
* Type for mutex_init()
*/
#define MUTEX_DEFAULT 0
#endif /* __XFS_SUPPORT_MUTEX_H__ */

View File

@ -1,23 +0,0 @@
#ifndef __XFS_SUPPORT_RWLOCK_H__
#define __XFS_SUPPORT_RWLOCK_H__
#include <sys/param.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/sx.h>
typedef struct sx rwlock_t;
typedef int wait_queue_head_t;
#define rwlock_init(lock) sx_init(lock, "rwlock")
#define rwlock_destroy(lock) sx_destroy(lock)
#define read_lock(lock) sx_slock(lock)
#define read_unlock(lock) sx_sunlock(lock)
#define write_lock(lock) sx_xlock(lock)
#define write_trylock(lock) sx_try_xlock(lock)
#define write_unlock(lock) sx_xunlock(lock)
#define rwlock_trypromote(lock) sx_try_upgrade(lock)
#define rwlock_demote(lock) sx_downgrade(lock)
#endif /* __XFS_SUPPORT_RWLOCK_H__ */

View File

@ -1,21 +0,0 @@
#ifndef __XFS_SUPPORT_RWSEM_H__
#define __XFS_SUPPORT_RWSEM_H__
#include <sys/param.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/sx.h>
#define rw_semaphore sx
#define init_rwsem(sem) sx_init(sem, "rwsem")
#define free_rwsem(sem) sx_destroy(sem)
#define down_read(sem) sx_slock(sem)
#define down_read_trylock(sem) sx_try_slock(sem)
#define down_write(sem) sx_xlock(sem)
#define down_write_trylock(sem) sx_try_xlock(sem)
#define up_read(sem) sx_sunlock(sem)
#define up_write(sem) sx_xunlock(sem)
#define downgrade_write(sem) sx_downgrade(sem)
#endif /* __XFS_SUPPORT_RWSEM_H__ */

View File

@ -1,53 +0,0 @@
/*-
* Copyright (c) 1992, 1993
* The Regents of the University of California. 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. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University 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 REGENTS 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 REGENTS 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.
*/
#ifndef __XFS_SUPPORT_SEMA_H__
#define __XFS_SUPPORT_SEMA_H__
#include <sys/sema.h>
/*
* sema_t structure just maps to struct sema in FreeBSD kernel.
*/
typedef struct sema sema_t;
#define init_sema(sp, val, c, d) sema_init(sp, val, c)
#define initnsema(sp, val, name) sema_init(sp, val, name)
#define psema(sp, b) sema_wait(sp)
#define vsema(sp) sema_post(sp)
#define valusema(sp) sema_value(sp)
#define freesema(sp) sema_destroy(sp)
#define cpsema(sp) sema_trywait(sp)
#endif /* __XFS_SUPPORT_SEMA_H__ */

View File

@ -1,42 +0,0 @@
#ifndef __XFS_SUPPORT_SPIN_H__
#define __XFS_SUPPORT_SPIN_H__
#include <sys/param.h>
#include <sys/types.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#define SPLDECL(s) register_t s
/*
* Map the spinlocks from IRIX to FreeBSD
*/
#define spinlock_init(lock, name) mtx_init(lock, name, NULL, MTX_DEF)
#define spinlock_destroy(lock) mtx_destroy(lock)
/*
* Map lock_t from IRIX to FreeBSD mutexes
*/
typedef struct mtx lock_t;
#define nested_spinunlock(lock) mtx_unlock(lock)
#define nested_spinlock(lock) mtx_lock(lock)
#define nested_spintrylock(lock) mtx_trylock(lock)
#define spin_lock(lock) mtx_lock(lock)
#define spin_unlock(lock) mtx_unlock(lock)
#if LOCK_DEBUG > 0
#define mutex_spinlock(lock) (spin_lock(lock),0)
#else
static __inline register_t
mutex_spinlock(lock_t *lock) { mtx_lock(lock); return 0; }
#endif
#define mutex_spinunlock(lock, s) \
do { \
spin_unlock(lock); \
if (s != 0) {} \
} while (0)
#endif /* __XFS_SUPPORT_SPIN_H__ */

View File

@ -1,49 +0,0 @@
/*
* Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it would be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*
* Further, this software is distributed without any warranty that it is
* free of the rightful claim of any third person regarding infringement
* or the like. Any license provided herein, whether implied or
* otherwise, applies only to this software file. Patent licenses, if
* any, provided herein do not apply to combinations of this program with
* other software, or any other product whatsoever.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write the Free Software Foundation, Inc., 59
* Temple Place - Suite 330, Boston MA 02111-1307, USA.
*
* Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
* Mountain View, CA 94043, or:
*
* http://www.sgi.com
*
* For further information regarding this notice, see:
*
* http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
*/
#ifndef __XFS_SUPPORT_H__
#define __XFS_SUPPORT_H__
#include <support/types.h>
#include <support/arch.h>
#include <support/kmem.h>
#include <support/mrlock.h>
#include <support/spin.h>
#include <support/sv.h>
#include <support/ktrace.h>
#include <support/mutex.h>
#include <support/sema.h>
#include <support/atomic.h>
#include <support/debug.h>
#include <support/uuid.h>
#include <support/time.h>
#endif /* __XFS_SUPPORT_H__ */

View File

@ -1,30 +0,0 @@
#ifndef __XFS_SUPPORT_SV_H__
#define __XFS_SUPPORT_SV_H__
#include <sys/condvar.h>
/*
* Synchronisation variables
*
* parameters "pri", "svf" and "rts" are not (yet?) implemented
*
*/
typedef struct cv sv_t;
#define init_sv(sv,type,name,flag) cv_init(sv, name)
#define sv_init(sv,flag,name) cv_init(sv, name)
/* sv_wait should exit with lock unlocked */
#define sv_wait(sv, pri, lock, spl) cv_wait_unlock(sv, lock)
#define sv_wait_sig(sv, pri, lock, spl) cv_wait_sig_nolock(sv, lock)
#define sv_signal(sv) cv_signal(sv)
#define sv_broadcast(sv) cv_broadcast(sv)
#define sv_destroy(sv) cv_destroy(sv)
#define SV_FIFO 0x0 /* sv_t is FIFO type */
#define SV_LIFO 0x2 /* sv_t is LIFO type */
#define SV_PRIO 0x4 /* sv_t is PRIO type */
#define SV_KEYED 0x6 /* sv_t is KEYED type */
#define SV_DEFAULT SV_FIFO
#endif /* __XFS_SUPPORT_SV_H__ */

View File

@ -1,37 +0,0 @@
/*
* Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it would be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*
* Further, this software is distributed without any warranty that it is
* free of the rightful claim of any third person regarding infringement
* or the like. Any license provided herein, whether implied or
* otherwise, applies only to this software file. Patent licenses, if
* any, provided herein do not apply to combinations of this program with
* other software, or any other product whatsoever.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write the Free Software Foundation, Inc., 59
* Temple Place - Suite 330, Boston MA 02111-1307, USA.
*
* Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
* Mountain View, CA 94043, or:
*
* http://www.sgi.com
*
* For further information regarding this notice, see:
*
* http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
*/
#ifndef __XFS_SUPPORT_TIME_H__
#define __XFS_SUPPORT_TIME_H__
#define delay(ticks) DELAY(ticks)
#endif /* __XFS_SUPPORT_TIME_H__ */

View File

@ -1,165 +0,0 @@
/*
* Copyright (c) 2000-2003 Silicon Graphics, Inc. All Rights Reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it would be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*
* Further, this software is distributed without any warranty that it is
* free of the rightful claim of any third person regarding infringement
* or the like. Any license provided herein, whether implied or
* otherwise, applies only to this software file. Patent licenses, if
* any, provided herein do not apply to combinations of this program with
* other software, or any other product whatsoever.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write the Free Software Foundation, Inc., 59
* Temple Place - Suite 330, Boston MA 02111-1307, USA.
*
* Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
* Mountain View, CA 94043, or:
*
* http://www.sgi.com
*
* For further information regarding this notice, see:
*
* http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
*/
#include <xfs_config.h>
#include <xfs_compat.h>
#include <xfs_types.h>
#include <xfs_arch.h>
#include <support/uuid.h>
#include <support/kmem.h>
#include <support/debug.h>
#include <support/mutex.h>
static mutex_t uuid_monitor;
static int uuid_table_size;
static uuid_t *uuid_table;
void
uuid_init(void)
{
mutex_init(&uuid_monitor, MUTEX_DEFAULT, "uuid_monitor");
}
void
uuid_cleanup(void)
{
mutex_destroy(&uuid_monitor);
}
/*
* uuid_getnodeuniq - obtain the node unique fields of a UUID.
*
* This is not in any way a standard or condoned UUID function;
* it just something that's needed for user-level file handles.
*/
void
uuid_getnodeuniq(uuid_t *uuid, int fsid [2])
{
char *uu = (char *)uuid;
/* on IRIX, this function assumes big-endian fields within
* the uuid, so we use INT_GET to get the same result on
* little-endian systems
*/
fsid[0] = (INT_GET(*(u_int16_t*)(uu+8), ARCH_CONVERT) << 16) +
INT_GET(*(u_int16_t*)(uu+4), ARCH_CONVERT);
fsid[1] = INT_GET(*(u_int32_t*)(uu ), ARCH_CONVERT);
}
void
uuid_create_nil(uuid_t *uuid)
{
memset(uuid, 0, sizeof(*uuid));
}
int
uuid_is_nil(uuid_t *uuid)
{
int i;
char *cp = (char *)uuid;
if (uuid == NULL)
return 0;
/* implied check of version number here... */
for (i = 0; i < sizeof *uuid; i++)
if (*cp++) return 0; /* not nil */
return 1; /* is nil */
}
int
uuid_equal(uuid_t *uuid1, uuid_t *uuid2)
{
return memcmp(uuid1, uuid2, sizeof(uuid_t)) ? 0 : 1;
}
/*
* Given a 128-bit uuid, return a 64-bit value by adding the top and bottom
* 64-bit words. NOTE: This function can not be changed EVER. Although
* brain-dead, some applications depend on this 64-bit value remaining
* persistent. Specifically, DMI vendors store the value as a persistent
* filehandle.
*/
__uint64_t
uuid_hash64(uuid_t *uuid)
{
__uint64_t *sp = (__uint64_t *)uuid;
return sp[0] + sp[1];
}
int
uuid_table_insert(uuid_t *uuid)
{
int i, hole;
mutex_lock(&uuid_monitor, PVFS);
for (i = 0, hole = -1; i < uuid_table_size; i++) {
if (uuid_is_nil(&uuid_table[i])) {
hole = i;
continue;
}
if (uuid_equal(uuid, &uuid_table[i])) {
mutex_unlock(&uuid_monitor);
return 0;
}
}
if (hole < 0) {
uuid_table = kmem_realloc(uuid_table,
(uuid_table_size + 1) * sizeof(*uuid_table),
uuid_table_size * sizeof(*uuid_table),
KM_SLEEP);
hole = uuid_table_size++;
}
uuid_table[hole] = *uuid;
mutex_unlock(&uuid_monitor);
return 1;
}
void
uuid_table_remove(uuid_t *uuid)
{
int i;
mutex_lock(&uuid_monitor, PVFS);
for (i = 0; i < uuid_table_size; i++) {
if (uuid_is_nil(&uuid_table[i]))
continue;
if (!uuid_equal(uuid, &uuid_table[i]))
continue;
uuid_create_nil(&uuid_table[i]);
break;
}
ASSERT(i < uuid_table_size);
mutex_unlock(&uuid_monitor);
}

View File

@ -1,45 +0,0 @@
/*
* Copyright (c) 2000-2003 Silicon Graphics, Inc. All Rights Reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it would be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*
* Further, this software is distributed without any warranty that it is
* free of the rightful claim of any third person regarding infringement
* or the like. Any license provided herein, whether implied or
* otherwise, applies only to this software file. Patent licenses, if
* any, provided herein do not apply to combinations of this program with
* other software, or any other product whatsoever.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write the Free Software Foundation, Inc., 59
* Temple Place - Suite 330, Boston MA 02111-1307, USA.
*
* Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
* Mountain View, CA 94043, or:
*
* http://www.sgi.com
*
* For further information regarding this notice, see:
*
* http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
*/
#ifndef __XFS_SUPPORT_UUID_H__
#define __XFS_SUPPORT_UUID_H__
void uuid_init(void);
void uuid_cleanup(void);
void uuid_create_nil(uuid_t *uuid);
int uuid_is_nil(uuid_t *uuid);
int uuid_equal(uuid_t *uuid1, uuid_t *uuid2);
void uuid_getnodeuniq(uuid_t *uuid, int fsid [2]);
__uint64_t uuid_hash64(uuid_t *uuid);
int uuid_table_insert(uuid_t *uuid);
void uuid_table_remove(uuid_t *uuid);
#endif /* __XFS_SUPPORT_UUID_H__ */

View File

@ -1,334 +0,0 @@
/*
* Copyright (c) 2001,2005 Russell Cattelan
* 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.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
*
* $FreeBSD$
*/
#include "xfs.h"
#include "xfs_types.h"
#include "xfs_inum.h"
#include "xfs_log.h"
#include "xfs_trans.h"
#include "xfs_sb.h"
#include "xfs_ag.h"
#include "xfs_dir.h"
#include "xfs_dir2.h"
#include "xfs_dmapi.h"
#include "xfs_mount.h"
#include "xfs_clnt.h"
#include "xfs_mountops.h"
#include <geom/geom.h>
#include <geom/geom_vfs.h>
xfs_buf_t *
xfs_buf_read_flags(xfs_buftarg_t *target, xfs_daddr_t blkno, size_t len, int flags)
{
struct buf *bp;
KASSERT((target != NULL), ("got NULL buftarg_t"));
if (bread(target->specvp, blkno, BBTOB(len), NOCRED, &bp)) {
printf("bread failed specvp %p blkno %jd BBTOB(len) %ld\n",
target->specvp, (intmax_t)blkno, (long)BBTOB(len));
bp = NULL;
}
/* not really sure what B_MANAGED really does for us
* maybe we should drop this and just stick with a locked buf
*/
if (flags & B_MANAGED)
bp->b_flags |= B_MANAGED;
xfs_buf_set_target(bp, target);
return (bp);
}
xfs_buf_t *
xfs_buf_get_flags(xfs_buftarg_t *target, xfs_daddr_t blkno, size_t len, int flags)
{
struct buf *bp = NULL;
KASSERT((target != NULL), ("got NULL buftarg_t"));
bp = getblk(target->specvp, blkno, BBTOB(len), 0, 0, 0);
if (bp != NULL)
xfs_buf_set_target(bp, target);
return (bp);
}
xfs_buf_t*
xfs_buf_get_empty(size_t size, xfs_buftarg_t *target)
{
struct buf *bp;
bp = geteblk(0, 0);
if (bp != NULL) {
bp->b_bufsize = size;
bp->b_bcount = size;
BUF_ASSERT_HELD(bp);
xfs_buf_set_target(bp, target);
}
return (bp);
}
xfs_buf_t*
xfs_buf_get_noaddr(size_t len, xfs_buftarg_t *target)
{
struct buf *bp;
if (len >= MAXPHYS)
return (NULL);
bp = geteblk(len, 0);
if (bp != NULL) {
BUF_ASSERT_HELD(bp);
xfs_buf_set_target(bp, target);
}
return (bp);
}
void
xfs_buf_free(xfs_buf_t *bp)
{
bp->b_flags |= B_INVAL;
BUF_KERNPROC(bp); /* ugly hack #1 */
if (bp->b_kvasize == 0) {
bp->b_saveaddr = bp->b_kvabase; /* ugly hack #2 */
bp->b_data = bp->b_saveaddr;
bp->b_bcount = 0;
bp->b_bufsize = 0;
}
brelse(bp);
}
void
xfs_buf_readahead(
xfs_buftarg_t *target,
xfs_daddr_t ioff,
size_t isize,
xfs_buf_flags_t flags)
{
daddr_t rablkno;
int rabsize;
rablkno = ioff;
rabsize = BBTOB(isize);
breada(target->specvp, &rablkno, &rabsize, 1, NOCRED);
}
void
xfs_buf_set_target(xfs_buf_t *bp, xfs_buftarg_t *targ)
{
bp->b_bufobj = &targ->specvp->v_bufobj;
bp->b_caller1 = targ;
}
xfs_buftarg_t *
xfs_buf_get_target(xfs_buf_t *bp)
{
return (xfs_buftarg_t *)bp->b_caller1;
}
int
XFS_bwrite(xfs_buf_t *bp)
{
int error;
if (bp->b_vp == NULL) {
error = xfs_buf_iorequest(bp);
if ((bp->b_flags & B_ASYNC) == 0) {
error = bufwait(bp);
#if 0
if (BUF_LOCKRECURSED(bp))
BUF_UNLOCK(bp);
else
brelse(bp);
#endif
brelse(bp);
}
return (error);
}
error = bwrite(bp);
return (error);
}
void
xfs_buf_pin(xfs_buf_t *bp)
{
bpin(bp);
}
void
xfs_buf_unpin(xfs_buf_t *bp)
{
bunpin(bp);
}
int
xfs_buf_ispin(xfs_buf_t *bp)
{
return bp->b_pin_count;
}
#if 0
void
xfs_buf_wait_unpin(
xfs_buf_t *bp)
{
bunpin_wait(bp);
}
#endif
/*
* Move data into or out of a buffer.
*/
void
xfs_buf_iomove(
xfs_buf_t *bp, /* buffer to process */
size_t boff, /* starting buffer offset */
size_t bsize, /* length to copy */
caddr_t data, /* data address */
xfs_buf_rw_t mode) /* read/write/zero flag */
{
printf("xfs_buf_iomove NI\n");
#ifdef RMC
size_t bend, cpoff, csize;
struct page *page;
bend = boff + bsize;
while (boff < bend) {
page = bp->b_pages[xfs_buf_btoct(boff + bp->b_offset)];
cpoff = xfs_buf_poff(boff + bp->b_offset);
csize = min_t(size_t,
PAGE_CACHE_SIZE-cpoff, bp->b_count_desired-boff);
ASSERT(((csize + cpoff) <= PAGE_CACHE_SIZE));
switch (mode) {
case XBRW_ZERO:
memset(page_address(page) + cpoff, 0, csize);
break;
case XBRW_READ:
memcpy(data, page_address(page) + cpoff, csize);
break;
case XBRW_WRITE:
memcpy(page_address(page) + cpoff, data, csize);
}
boff += csize;
data += csize;
}
#endif
}
/*
* Handling of buffer targets (buftargs).
*/
/*
* Wait for any bufs with callbacks that have been submitted but
* have not yet returned... walk the hash list for the target.
*/
void
xfs_wait_buftarg(
xfs_buftarg_t *bp)
{
printf("xfs_wait_buftarg(%p) NI\n", bp);
}
int
xfs_flush_buftarg(
xfs_buftarg_t *btp,
int wait)
{
int error = 0;
error = vinvalbuf(btp->specvp, V_SAVE | V_NORMAL, 0, 0);
return error;
}
void
xfs_free_buftarg(
xfs_buftarg_t *btp,
int external)
{
xfs_flush_buftarg(btp, /* wait */ 0);
kmem_free(btp, sizeof(*btp));
}
int
xfs_readonly_buftarg(
xfs_buftarg_t *btp)
{
struct g_consumer *cp;
KASSERT(btp->specvp->v_bufobj.bo_ops == &xfs_bo_ops,
("Bogus xfs_buftarg_t pointer"));
cp = btp->specvp->v_bufobj.bo_private;
return (cp->acw == 0);
}
#if 0
void
xfs_relse_buftarg(
xfs_buftarg_t *btp)
{
printf("xfs_relse_buftargNI %p\n",btp);
}
#endif
unsigned int
xfs_getsize_buftarg(
xfs_buftarg_t *btp)
{
struct g_consumer *cp;
cp = btp->specvp->v_bufobj.bo_private;
return (cp->provider->sectorsize);
}
int
xfs_setsize_buftarg(
xfs_buftarg_t *btp,
unsigned int blocksize,
unsigned int sectorsize)
{
printf("xfs_setsize_buftarg NI %p\n",btp);
return 0;
}
xfs_buftarg_t *
xfs_alloc_buftarg(
struct vnode *bdev,
int external)
{
xfs_buftarg_t *btp;
btp = kmem_zalloc(sizeof(*btp), KM_SLEEP);
btp->dev = bdev->v_rdev;
btp->specvp = bdev;
return btp;
}

View File

@ -1,348 +0,0 @@
/*
* Copyright (c) 2000-2003 Silicon Graphics, Inc. All Rights Reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it would be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*
* Further, this software is distributed without any warranty that it is
* free of the rightful claim of any third person regarding infringement
* or the like. Any license provided herein, whether implied or
* otherwise, applies only to this software file. Patent licenses, if
* any, provided herein do not apply to combinations of this program with
* other software, or any other product whatsoever.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write the Free Software Foundation, Inc., 59
* Temple Place - Suite 330, Boston MA 02111-1307, USA.
*
* Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
* Mountain View, CA 94043, or:
*
* http://www.sgi.com
*
* For further information regarding this notice, see:
*
* http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
*/
#ifndef __XFS_BUF_H__
#define __XFS_BUF_H__
#include <sys/bio.h>
#include <sys/buf.h>
struct xfs_buf;
struct xfs_mount;
struct vnode;
typedef struct buf xfs_buf_t;
typedef uint32_t xfs_buf_flags_t;
#define xfs_buf buf
extern struct buf_ops xfs_bo_ops;
typedef enum {
XBRW_READ = 1, /* transfer into target memory */
XBRW_WRITE = 2, /* transfer from target memory */
XBRW_ZERO = 3, /* Zero target memory */
} xfs_buf_rw_t;
/* Buffer Read and Write Routines */
extern void xfs_buf_ioend(xfs_buf_t *, int);
extern void xfs_buf_ioerror(xfs_buf_t *, int);
extern int xfs_buf_iostart(xfs_buf_t *, xfs_buf_flags_t);
extern int xfs_buf_iorequest(xfs_buf_t *);
extern int xfs_buf_iowait(xfs_buf_t *);
extern void xfs_buf_iomove(xfs_buf_t *, size_t, size_t, xfs_caddr_t, xfs_buf_rw_t);
/* Pinning Buffer Storage in Memory */
extern void xfs_buf_pin(xfs_buf_t *);
extern void xfs_buf_unpin(xfs_buf_t *);
extern int xfs_buf_ispin(xfs_buf_t *);
typedef void (*xfs_buf_iodone_t)(struct xfs_buf *); /* call-back function on I/O completion */
typedef void (*xfs_buf_relse_t)(struct xfs_buf *); /* call-back function on I/O completion */
typedef int (*xfs_buf_bdstrat_t)(struct xfs_buf *);
typedef struct xfs_buftarg {
/* this probaby redundant info, but stick with linux conventions for now */
unsigned int bt_bsize;
unsigned int bt_sshift;
size_t bt_smask;
struct cdev *dev;
struct vnode *specvp;
} xfs_buftarg_t;
/* Finding and Reading Buffers */
extern void xfs_buf_readahead(xfs_buftarg_t *, xfs_off_t, size_t, xfs_buf_flags_t);
/* Misc buffer rountines */
extern int xfs_readonly_buftarg(xfs_buftarg_t *);
/* These are just for xfs_syncsub... it sets an internal variable
* then passes it to VOP_FLUSH_PAGES or adds the flags to a newly gotten buf_t
*/
#define XBF_DONT_BLOCK 0
#define XFS_B_ASYNC B_ASYNC
#define XFS_B_DELWRI B_DELWRI
#define XFS_B_READ BIO_READ
#define XFS_B_WRITE BIO_WRITE
#define XFS_B_STALE B_INVAL
#define XFS_BUF_LOCK 0
#define XFS_BUF_TRYLOCK 0
#define XFS_BUF_MAPPED 0
#define BUF_BUSY 0
#define XBF_ORDERED 0
/* debugging routines might need this */
#define XFS_BUF_BFLAGS(x) ((x)->b_flags)
#define XFS_BUF_ZEROFLAGS(x) ((x)->b_flags = 0)
#define XFS_BUF_STALE(x) ((x)->b_flags |= (XFS_B_STALE|B_NOCACHE))
#define XFS_BUF_UNSTALE(x) ((x)->b_flags &= ~(XFS_B_STALE|B_NOCACHE))
#define XFS_BUF_ISSTALE(x) ((x)->b_flags & (XFS_B_STALE|B_NOCACHE))
#define XFS_BUF_SUPER_STALE(x) {(x)->b_flags |= (XFS_B_STALE|B_NOCACHE); \
(x)->b_flags &= ~(XFS_B_DELWRI|B_CACHE);}
#define XFS_BUF_MANAGE B_MANAGED
#define XFS_BUF_UNMANAGE(x) ((x)->b_flags &= ~B_MANAGED)
#define XFS_BUF_DELAYWRITE(x) ((x)->b_flags |= XFS_B_DELWRI)
#define XFS_BUF_UNDELAYWRITE(x) ((x)->b_flags &= ~XFS_B_DELWRI)
#define XFS_BUF_ISDELAYWRITE(x) ((x)->b_flags & XFS_B_DELWRI)
#define XFS_BUF_ERROR(x,no) xfs_buf_set_error((x), (no))
#define XFS_BUF_GETERROR(x) xfs_buf_get_error(x)
#define XFS_BUF_ISERROR(x) (((x)->b_ioflags & BIO_ERROR) != 0)
void static __inline__
xfs_buf_set_error(struct buf *bp, int err)
{
bp->b_ioflags |= BIO_ERROR;
bp->b_error = err;
}
int static __inline__
xfs_buf_get_error(struct buf *bp)
{
return XFS_BUF_ISERROR(bp) ? (bp->b_error ? bp->b_error : EIO) : 0;
}
#define XFS_BUF_DONE(x) ((x)->b_flags |= B_CACHE)
#define XFS_BUF_UNDONE(x) ((x)->b_flags &= ~B_CACHE)
#define XFS_BUF_ISDONE(x) ((x)->b_flags & B_CACHE)
#define XFS_BUF_BUSY(x) ((x)->b_flags |= BUF_BUSY)
#define XFS_BUF_UNBUSY(x) ((x)->b_flags &= ~BUF_BUSY)
#define XFS_BUF_ISBUSY(x) (1)
#define XFS_BUF_ASYNC(x) ((x)->b_flags |= B_ASYNC)
#define XFS_BUF_UNASYNC(x) ((x)->b_flags &= ~B_ASYNC)
#define XFS_BUF_ISASYNC(x) ((x)->b_flags & B_ASYNC)
#define XFS_BUF_ORDERED(bp) ((bp)->b_flags |= XBF_ORDERED)
#define XFS_BUF_UNORDERED(bp) ((bp)->b_flags &= ~XBF_ORDERED)
#define XFS_BUF_ISORDERED(bp) ((bp)->b_flags & XBF_ORDERED)
#define XFS_BUF_FLUSH(x) ((x)->b_flags |= B_00800000)
#define XFS_BUF_UNFLUSH(x) ((x)->b_flags &= ~B_00800000)
#define XFS_BUF_ISFLUSH(x) ((x)->b_flags & B_00800000)
#define XFS_BUF_SHUT(x) printf("XFS_BUF_SHUT not implemented yet\n")
#define XFS_BUF_UNSHUT(x) printf("XFS_BUF_UNSHUT not implemented yet\n")
#define XFS_BUF_ISSHUT(x) (0)
#define XFS_BUF_HOLD(x) ((void)0)
#define XFS_BUF_UNHOLD(x) ((void)0)
#define XFS_BUF_READ(x) ((x)->b_iocmd = BIO_READ)
#define XFS_BUF_UNREAD(x) ((x)->b_iocmd = 0)
#define XFS_BUF_ISREAD(x) ((x)->b_iocmd == BIO_READ)
#define XFS_BUF_WRITE(x) ((x)->b_iocmd = BIO_WRITE)
#define XFS_BUF_UNWRITE(x) ((x)->b_iocmd = 0)
#define XFS_BUF_ISWRITE(x) ((x)->b_iocmd == BIO_WRITE)
#define XFS_BUF_ISUNINITIAL(x) (0)
#define XFS_BUF_UNUNINITIAL(x) (0)
#define XFS_BUF_IODONE_FUNC(x) (x)->b_iodone
#define XFS_BUF_SET_IODONE_FUNC(x, f) (x)->b_iodone = (f)
#define XFS_BUF_CLR_IODONE_FUNC(x) (x)->b_iodone = NULL
#define XFS_BUF_SET_BDSTRAT_FUNC(x, f) do { if(f != NULL) {} } while(0)
#define XFS_BUF_CLR_BDSTRAT_FUNC(x) ((void)0)
#define XFS_BUF_BP_ISMAPPED(bp) (1)
#define XFS_BUF_FSPRIVATE(buf, type) \
((type)(buf)->b_fsprivate1)
#define XFS_BUF_SET_FSPRIVATE(buf, value) \
(buf)->b_fsprivate1 = (void *)(value)
#define XFS_BUF_FSPRIVATE2(buf, type) \
((type)(buf)->b_fsprivate2)
#define XFS_BUF_SET_FSPRIVATE2(buf, value) \
(buf)->b_fsprivate2 = (void *)(value)
#define XFS_BUF_FSPRIVATE3(buf, type) \
((type)(buf)->b_fsprivate3)
#define XFS_BUF_SET_FSPRIVATE3(buf, value) \
(buf)->b_fsprivate3 = (void *)(value)
#define XFS_BUF_SET_START(buf) \
printf("XFS_BUF_SET_START: %s:%d\n", __FILE__, __LINE__)
#define XFS_BUF_SET_BRELSE_FUNC(buf, value) \
do { \
printf("XFS_BUF_SET_BRELSE_FUNC: %s:%d\n", \
__FILE__, __LINE__); \
if (value != NULL ) {} \
} while(0)
#define XFS_BUF_PTR(bp) (xfs_caddr_t)((bp)->b_data)
static __inline xfs_caddr_t
xfs_buf_offset(xfs_buf_t *bp, size_t offset)
{
return XFS_BUF_PTR(bp) + offset;
}
#define XFS_BUF_SET_PTR(bp, val, count) \
do { \
(bp)->b_data = (val); \
(bp)->b_bcount = (count); \
} while(0)
#define XFS_BUF_ADDR(bp) ((bp)->b_blkno)
#define XFS_BUF_SET_ADDR(bp, blk) \
((bp)->b_blkno = blk)
#define XFS_BUF_OFFSET(bp) ((bp)->b_offset)
#define XFS_BUF_SET_OFFSET(bp, off) \
((bp)->b_offset = off)
#define XFS_BUF_COUNT(bp) ((bp)->b_bcount)
#define XFS_BUF_SET_COUNT(bp, cnt) \
((bp)->b_bcount = cnt)
#define XFS_BUF_SIZE(bp) ((bp)->b_bufsize)
#define XFS_BUF_SET_SIZE(bp, cnt) \
((bp)->b_bufsize = cnt)
#define XFS_BUF_SET_VTYPE_REF(bp, type, ref)
#define XFS_BUF_SET_VTYPE(bp, type)
#define XFS_BUF_SET_REF(bp, ref)
#define XFS_BUF_VALUSEMA(bp) (BUF_ISLOCKED(bp) ? 0 : 1)
#define XFS_BUF_CPSEMA(bp) \
(BUF_LOCK(bp, LK_EXCLUSIVE|LK_CANRECURSE | LK_SLEEPFAIL, NULL) == 0)
#define XFS_BUF_PSEMA(bp,x) BUF_LOCK(bp, LK_EXCLUSIVE|LK_CANRECURSE, NULL)
#define XFS_BUF_VSEMA(bp) BUF_UNLOCK(bp)
#define XFS_BUF_V_IODONESEMA(bp) bdone(bp)
/* setup the buffer target from a buftarg structure */
#define XFS_BUF_SET_TARGET(bp, target) \
xfs_buf_set_target(bp, target)
void xfs_buf_set_target(xfs_buf_t *, xfs_buftarg_t *);
xfs_buftarg_t *xfs_buf_get_target(xfs_buf_t *);
/* return the dev_t being used */
#define XFS_BUF_TARGET(bp) xfs_buf_get_target(bp)
#define XFS_BUFTARG_NAME(targp) devtoname((targp)->dev)
#define XFS_BUF_SET_VTYPE_REF(bp, type, ref)
#define XFS_BUF_SET_VTYPE(bp, type)
#define XFS_BUF_SET_REF(bp, ref)
#define XFS_BUF_ISPINNED(bp) xfs_buf_ispin(bp)
xfs_buf_t *
xfs_buf_read_flags(xfs_buftarg_t *, xfs_daddr_t, size_t, int);
#define xfs_buf_read(target, blkno, len, flags) \
xfs_buf_read_flags(target, blkno, len, \
XFS_BUF_LOCK | XFS_BUF_MAPPED)
xfs_buf_t *
xfs_buf_get_flags(xfs_buftarg_t *, xfs_daddr_t, size_t, int);
#define xfs_buf_get(target, blkno, len, flags) \
xfs_buf_get_flags(target, blkno, len, \
XFS_BUF_LOCK | XFS_BUF_MAPPED)
/* the return value is never used ... why does linux define this functions this way? */
static inline int xfs_bawrite(void *mp, xfs_buf_t *bp)
{
/* Ditto for xfs_bawrite
bp->b_fspriv3 = mp;
bp->b_strat = xfs_bdstrat_cb;
xfs_buf_delwri_dequeue(bp);
return xfs_buf_iostart(bp, XBF_WRITE | XBF_ASYNC | _XBF_RUN_QUEUES);
*/
bawrite(bp);
return 0;
}
static inline int xfs_bdwrite(void *mp, xfs_buf_t *bp)
{
/* this is for io shutdown checking need to do this at some point RMC */
/* probably should just change xfs to call a buf write function */
#if 0 /* RMC */
bp->b_strat = xfs_bdstrat_cb;
bp->b_fspriv3 = mp;
return xfs_buf_iostart(bp, XBF_DELWRI | XBF_ASYNC);
#endif
bdwrite(bp);
return 0;
}
#define xfs_bpin(bp) xfs_buf_pin(bp)
#define xfs_bunpin(bp) xfs_buf_unpin(bp)
#define xfs_buf_relse(bp) brelse(bp)
#define xfs_bp_mapin(bp) bp_mapin(bp)
#define xfs_xfsd_list_evict(x) _xfs_xfsd_list_evict(x)
#define xfs_buftrace(x,y) CTR2(KTR_BUF, "%s bp %p flags %X", bp, bp->b_flags)
#define xfs_biodone(bp) bufdone_finish(bp)
#define xfs_incore(xfs_buftarg,blkno,len,lockit) \
incore(&xfs_buftarg->specvp->v_bufobj, blkno);
#define xfs_biomove(bp, off, len, data, rw) \
xfs_buf_iomove((bp), (off), (len), (data), \
((rw) == XFS_B_WRITE) ? XBRW_WRITE : XBRW_READ)
#define xfs_biozero(bp, off, len) \
xfs_buf_iomove((bp), (off), (len), NULL, XBRW_ZERO)
/* already a function xfs_bwrite... fix this */
#define XFS_bdwrite(bp) bdwrite(bp)
#define xfs_iowait(bp) bufwait(bp)
#define XFS_bdstrat(bp) xfs_buf_iorequest(bp)
#define xfs_baread(target, rablkno, ralen) \
xfs_buf_readahead((target), (rablkno), (ralen), XBF_DONT_BLOCK)
struct xfs_mount;
int XFS_bwrite(xfs_buf_t *bp);
xfs_buf_t* xfs_buf_get_empty(size_t, xfs_buftarg_t *targ);
xfs_buf_t* xfs_buf_get_noaddr(size_t, xfs_buftarg_t *targ);
void xfs_buf_free(xfs_buf_t *);
extern void xfs_bwait_unpin(xfs_buf_t *bp);
extern xfs_buftarg_t *xfs_alloc_buftarg(struct vnode *, int);
extern void xfs_free_buftarg(xfs_buftarg_t *, int);
extern void xfs_wait_buftarg(xfs_buftarg_t *);
extern int xfs_setsize_buftarg(xfs_buftarg_t *, unsigned int, unsigned int);
extern unsigned int xfs_getsize_buftarg(struct xfs_buftarg *);
extern int xfs_flush_buftarg(xfs_buftarg_t *, int);
#define xfs_binval(buftarg) xfs_flush_buftarg(buftarg, 1)
#define XFS_bflush(buftarg) xfs_flush_buftarg(buftarg, 1)
#endif

View File

@ -1,173 +0,0 @@
#ifndef __XFS_COMPAT_H__
#define __XFS_COMPAT_H__
#include <sys/param.h>
#include <sys/libkern.h>
#include <sys/limits.h>
#include <sys/uuid.h>
#include <sys/conf.h>
#include <sys/sbuf.h>
#include <sys/stat.h>
#include <sys/ioccom.h>
#include <sys/fcntl.h>
#include <sys/dirent.h>
#include <sys/ktr.h>
#include <sys/kdb.h>
#ifdef _KERNEL
#define __KERNEL__
#endif
#define printk printf
#define MAJOR(x) major(x)
#define MINOR(x) minor(x)
/*
* SYSV compatibility types missing in FreeBSD.
*/
typedef unsigned long ulong;
typedef unsigned int uint;
typedef unsigned short ushort;
/*
* Additional type declarations for XFS.
*/
typedef signed char __s8;
typedef unsigned char __u8;
typedef signed short int __s16;
typedef unsigned short int __u16;
typedef signed int __s32;
typedef unsigned int __u32;
typedef signed long long int __s64;
typedef unsigned long long int __u64;
/* linus now has sparse which expects big endian or little endian */
typedef __u16 __be16;
typedef __u32 __be32;
typedef __u64 __be64;
/*
* Linux types with direct FreeBSD conterparts
*/
typedef off_t loff_t;
typedef struct timespec timespec_t;
typedef struct uuid uuid_t;
typedef struct fid fid_t;
typedef dev_t os_dev_t;
/*
* Linux block devices are device vnodes in FreeBSD.
*/
#define block_device vnode
/*
* Get the current CPU ID.
*/
#define smp_processor_id() PCPU_GET(cpuid)
/*
* FreeBSD does not have BITS_PER_LONG defined.
*/
#if defined(LONG_BIT)
#define BITS_PER_LONG LONG_BIT
#elif defined(__i386__)
#define BITS_PER_LONG 32
#endif
#define rol32(x, y) (((x)<<(y))|((x)>>(32-(y))))
/*
* boolean_t is enum on Linux, int on FreeBSD.
* Provide value defines.
*/
#define B_FALSE 0
#define B_TRUE 1
/*
* GCC 3.x static branch prediction hints
*/
#if __GNUC__ < 3
#define __builtin_expect(x, expected_value) (x)
#endif
#ifndef likely
#define likely(x) __builtin_expect((x), 1)
#endif
#ifndef unlikely
#define unlikely(x) __builtin_expect((x), 0)
#endif
/*
* ANSI and GCC extension keywords compatibity
*/
#ifndef inline
#define inline __inline__
#endif
#ifndef asm
#define asm __asm
#endif
#ifndef typeof
#define typeof __typeof
#endif
/*
* Miscellaneous limit constants
*/
#define MAX_LFS_FILESIZE 0x7fffffffffffffffLL
/*
* Map simple functions to their FreeBSD kernel equivalents
*/
#ifndef copy_to_user
#define copy_to_user(dst, src, len) copyout((src), (dst), (len))
#endif
#ifndef copy_from_user
#define copy_from_user(dst, src, len) copyin((src), (dst), (len))
#endif
/*
* Map simple global vairables to FreeBSD kernel equivalents
*/
#if !defined(xfs_physmem)
#define xfs_physmem physmem
#endif
#ifndef HZ
#define HZ hz
#endif
/*
* These should be implemented properly for all architectures
* we want to support.
*/
#define get_unaligned(ptr) (*(ptr))
#define put_unaligned(val, ptr) ((void)( *(ptr) = (val) ))
/*
* Linux type-safe min/max macros.
*/
#define min_t(type,x,y) MIN((x),(y))
#define max_t(type,x,y) MAX((x),(y))
typedef struct mtx xfs_mutex_t;
/*
* Cedentials manipulation.
*/
#define current_fsuid(credp) (credp)->cr_uid
#define current_fsgid(credp) (credp)->cr_groups[0]
#define PAGE_CACHE_SIZE PAGE_SIZE
#define IS_ERR(err) (err)
static inline unsigned long ffz(unsigned long val)
{
return ffsl(~val);
}
#endif /* __XFS_COMPAT_H__ */

View File

@ -1,38 +0,0 @@
#ifndef __XFS_CONFIG_H__
#define __XFS_CONFIG_H__
#define HAVE_FID 1
/*
* Linux config variables, harcoded to values desirable for FreeBSD.
*/
#define CONFIG_SYSCTL 1
#define CONFIG_LBD 1
#define CONFIG_XFS_TRACE 0
/*
* Tracing.
*/
#if CONFIG_XFS_TRACE == 1
#define XFS_ALLOC_TRACE 1
#define XFS_ALLOC_TRACE 1
#define XFS_ATTR_TRACE 1
#define XFS_BLI_TRACE 1
#define XFS_BMAP_TRACE 1
#define XFS_BMBT_TRACE 1
#define XFS_DIR_TRACE 1
#define XFS_DIR2_TRACE 1
#define XFS_DQUOT_TRACE 1
#define XFS_ILOCK_TRACE 1
#define XFS_LOG_TRACE 1
#define XFS_RW_TRACE 1
#endif
/*
* XFS config defines.
*/
#define XFS_BIG_BLKNOS 1
#define XFS_BIG_INUMS 0
#undef XFS_STATS_OFF
#endif /* __XFS_CONFIG_H__ */

View File

@ -1,46 +0,0 @@
/*
* Copyright (c) 2000-2002 Silicon Graphics, Inc. All Rights Reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it would be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*
* Further, this software is distributed without any warranty that it is
* free of the rightful claim of any third person regarding infringement
* or the like. Any license provided herein, whether implied or
* otherwise, applies only to this software file. Patent licenses, if
* any, provided herein do not apply to combinations of this program with
* other software, or any other product whatsoever.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write the Free Software Foundation, Inc., 59
* Temple Place - Suite 330, Boston MA 02111-1307, USA.
*
* Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
* Mountain View, CA 94043, or:
*
* http://www.sgi.com
*
* For further information regarding this notice, see:
*
* http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
*/
#ifndef __XFS_CRED_H__
#define __XFS_CRED_H__
#include <sys/ucred.h>
/*
* struct cred is struct ucred on FreeBSD
*/
typedef struct ucred cred_t;
#define cred ucred
#define capable(cap) (1)
#define capable_cred(cr, cap) (1)
#endif /* __XFS_CRED_H__ */

View File

@ -1,144 +0,0 @@
/*
* Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*
* Further, this software is distributed without any warranty that it is
* free of the rightful claim of any third person regarding infringement
* or the like. Any license provided herein, whether implied or
* otherwise, applies only to this software file. Patent licenses, if
* any, provided herein do not apply to combinations of this program with
* other software, or any other product whatsoever.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write the Free Software Foundation, Inc., 59
* Temple Place - Suite 330, Boston MA 02111-1307, USA.
*
* Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
* Mountain View, CA 94043, or:
*
* http://www.sgi.com
*
* For further information regarding this notice, see:
*
* http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
*/
#include "xfs.h"
#include "xfs_types.h"
#include "xfs_inum.h"
#include "xfs_log.h"
#include "xfs_trans.h"
#include "xfs_sb.h"
#include "xfs_ag.h"
#include "xfs_dir.h"
#include "xfs_dir2.h"
#include "xfs_dmapi.h"
#include "xfs_mount.h"
static int nopkg(void);
static __inline int
nopkg()
{
return (ENOSYS);
}
int dmapi_init(void);
int
dmapi_init (void)
{
return (0);
}
void dmapi_uninit(void);
void
dmapi_uninit (void)
{
}
int dm_data_event(void);
int
dm_data_event (void)
{
return nopkg();
}
int dm_namesp_event(void);
int
dm_namesp_event (void)
{
return nopkg();
}
/* The following stubs are for routines needed for the X/Open
* version of DMAPI.
*/
int xfs_dm_mount(xfs_vfs_t *, xfs_vnode_t *, char *, char *);
int
xfs_dm_mount(
xfs_vfs_t *vfsp,
xfs_vnode_t *mvp,
char *dir_name,
char *fsname)
{
return nopkg();
}
int
dm_send_destroy_event(bhv_desc_t *bdp, dm_right_t vp_right);
int
dm_send_destroy_event(bhv_desc_t *bdp, dm_right_t vp_right)
{
return nopkg();
}
int
dm_send_mount_event(xfs_vfs_t *vfsp, dm_right_t vfsp_right, bhv_desc_t *bdp,
dm_right_t vp_right, bhv_desc_t *rootbdp, dm_right_t rootvp_right,
char *name1, char *name2);
int
dm_send_mount_event(xfs_vfs_t *vfsp, dm_right_t vfsp_right, bhv_desc_t *bdp,
dm_right_t vp_right, bhv_desc_t *rootbdp, dm_right_t rootvp_right,
char *name1, char *name2)
{
return nopkg();
}
int
dm_send_namesp_event(dm_eventtype_t event, bhv_desc_t *bdp1,
dm_right_t vp1_right, bhv_desc_t *bdp2, dm_right_t vp2_right,
char *name1, char *name2, mode_t mode, int retcode, int flags);
int
dm_send_namesp_event(dm_eventtype_t event, bhv_desc_t *bdp1,
dm_right_t vp1_right, bhv_desc_t *bdp2, dm_right_t vp2_right,
char *name1, char *name2, mode_t mode, int retcode, int flags)
{
return nopkg();
}
void
dm_send_unmount_event(xfs_vfs_t *vfsp, xfs_vnode_t *vp, dm_right_t vfsp_right,
mode_t mode, int retcode, int flags);
void
dm_send_unmount_event(xfs_vfs_t *vfsp, xfs_vnode_t *vp, dm_right_t vfsp_right,
mode_t mode, int retcode, int flags)
{
}
int
dm_vp_to_handle (xfs_vnode_t *vp, xfs_handle_t *handlep);
int
dm_vp_to_handle (xfs_vnode_t *vp, xfs_handle_t *handlep)
{
return nopkg();
}

Some files were not shown because too many files have changed in this diff Show More