Merge from vmcontention
This commit is contained in:
commit
a345907061
@ -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
|
||||
|
@ -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.
|
||||
#
|
||||
|
@ -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
|
||||
|
@ -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 \
|
||||
|
@ -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
109
lib/libc/sys/bindat.2
Normal 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.
|
@ -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
109
lib/libc/sys/connectat.2
Normal 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.
|
@ -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);
|
||||
}
|
@ -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 {
|
||||
|
@ -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>
|
@ -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 .
|
@ -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);
|
||||
}
|
@ -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>
|
@ -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.
|
@ -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);
|
||||
}
|
@ -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.
|
@ -1,3 +0,0 @@
|
||||
tcp/ tcp tcp/
|
||||
tcplisten/ tcplisten tcplisten/
|
||||
fs/ file fs/
|
@ -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.
|
@ -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 .
|
@ -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
|
||||
|
@ -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_
|
||||
|
@ -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
|
||||
|
@ -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 */
|
||||
};
|
||||
|
@ -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 */
|
||||
};
|
||||
|
@ -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;
|
||||
};
|
||||
|
@ -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); }
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -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.
|
||||
|
@ -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$
|
@ -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_ */
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
@ -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_ */
|
@ -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_ */
|
@ -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_ */
|
@ -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);
|
||||
}
|
@ -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_ */
|
@ -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
|
||||
* ...
|
||||
*/
|
@ -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_ */
|
@ -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);
|
||||
}
|
@ -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_ */
|
@ -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);
|
@ -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
@ -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_ */
|
@ -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;
|
@ -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);
|
||||
}
|
@ -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
|
@ -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);
|
||||
}
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
@ -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
@ -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];
|
||||
};
|
@ -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;
|
@ -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);
|
||||
}
|
@ -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 *);
|
@ -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);
|
@ -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);
|
||||
}
|
@ -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 *);
|
@ -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
@ -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))
|
@ -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);
|
@ -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 **);
|
@ -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,
|
||||
};
|
@ -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 */
|
||||
};
|
@ -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 */
|
@ -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);
|
@ -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,
|
||||
};
|
@ -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;
|
||||
|
@ -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__ */
|
@ -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);
|
||||
}
|
||||
|
@ -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__ */
|
@ -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;
|
||||
}
|
@ -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__ */
|
@ -1,3 +0,0 @@
|
||||
#include <support/kmem.h>
|
||||
|
||||
MALLOC_DEFINE(M_XFS, "XFSALLOC", "XFS memory");
|
@ -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__ */
|
@ -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;
|
||||
}
|
@ -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__ */
|
@ -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__ */
|
@ -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;
|
||||
}
|
@ -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__ */
|
@ -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__ */
|
@ -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__ */
|
@ -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__ */
|
@ -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__ */
|
@ -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__ */
|
@ -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__ */
|
@ -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__ */
|
@ -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__ */
|
@ -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);
|
||||
}
|
@ -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__ */
|
@ -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;
|
||||
}
|
@ -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
|
@ -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__ */
|
@ -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__ */
|
@ -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__ */
|
@ -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
Loading…
Reference in New Issue
Block a user