Garbage collect XFS bits which are now already completely disconnected

from the tree since few months.

This is not targeted for MFC.
This commit is contained in:
Attilio Rao 2013-03-02 15:33:54 +00:00
parent 258bee160c
commit 67f1f66fc7
167 changed files with 2 additions and 108267 deletions

View File

@ -38,6 +38,8 @@
# xargs -n1 | sort | uniq -d;
# done
# 20130302: XFS support removed
OLD_FILES+=usr/share/man/man5/xfs.5.gz
# 20130116: removed long unused directories for .1aout section manpages
OLD_FILES+=usr/share/man/en.ISO8859-1/man1aout
OLD_FILES+=usr/share/man/en.UTF-8/man1aout

View File

@ -1,108 +0,0 @@
.\"
.\" Copyright (c) 2007 Craig Rodrigues
.\" All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\" 1. Redistributions of source code must retain the above copyright
.\" notice, this list of conditions and the following disclaimer.
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in the
.\" documentation and/or other materials provided with the distribution.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
.\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.\"
.\" $FreeBSD$
.\"
.Dd January 16, 2011
.Dt XFS 5
.Os
.Sh NAME
.Nm xfs
.Nd "XFS file system"
.Sh SYNOPSIS
To link into the kernel:
.Bd -ragged -offset indent
.Cd "options XFS"
.Ed
.Pp
To load as a kernel loadable module:
.Pp
.Dl "kldload xfs"
.Sh DESCRIPTION
The
.Nm
driver will permit the
.Fx
kernel to access
.Tn XFS
file systems.
.Sh EXAMPLES
To mount a
.Nm
volume located on
.Pa /dev/ad1s1 :
.Pp
.Dl "mount -t xfs -o ro /dev/ad1s1 /mnt"
.Sh SEE ALSO
.Xr nmount 2 ,
.Xr unmount 2 ,
.Xr fstab 5 ,
.Xr mount 8
.Sh NOTES
The
.Pa sysutils/xfsprogs
port contains the
.Cm mkfs.xfs
utility for
creating XFS file systems, and also other utilities for analyzing,
and repairing XFS file systems.
.Sh HISTORY
XFS was originally written by SGI for the IRIX operating system.
SGI ported XFS to Linux, and released the source code under the GNU
Public License. For more details, see:
.Pa http://oss.sgi.com/projects/xfs
.Pp
The port to
.Fx
was based on the Linux port, and started by
.An -nosplit
.An Russell Cattelan Aq cattelan@xfs.org ,
.An Alexander Kabaev Aq kan@FreeBSD.org ,
and
.An Craig Rodrigues Aq rodrigc@FreeBSD.org .
.Pp
The
.Nm
file system support
first appeared in
.Fx 7.0 .
.Sh AUTHORS
This manual page was written by
.An Craig Rodrigues Aq rodrigc@FreeBSD.org .
.Sh CAVEATS
The port of XFS to
.Fx
is currently incomplete.
Only read-only access is supported for XFS volumes.
Writing to a volume is not supported.
.Pp
The
.Fl p
flag to
.Cm mkfs.xfs
can be used to create an XFS file system which is populated with files
and other metadata.
This can be used to quickly create a read-only file system which
can be tested on
.Fx .

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,53 +0,0 @@
/*-
* Copyright (c) 1992, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#ifndef __XFS_SUPPORT_SEMA_H__
#define __XFS_SUPPORT_SEMA_H__
#include <sys/sema.h>
/*
* sema_t structure just maps to struct sema in FreeBSD kernel.
*/
typedef struct sema sema_t;
#define init_sema(sp, val, c, d) sema_init(sp, val, c)
#define initnsema(sp, val, name) sema_init(sp, val, name)
#define psema(sp, b) sema_wait(sp)
#define vsema(sp) sema_post(sp)
#define valusema(sp) sema_value(sp)
#define freesema(sp) sema_destroy(sp)
#define cpsema(sp) sema_trywait(sp)
#endif /* __XFS_SUPPORT_SEMA_H__ */

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,334 +0,0 @@
/*
* Copyright (c) 2001,2005 Russell Cattelan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $FreeBSD$
*/
#include "xfs.h"
#include "xfs_types.h"
#include "xfs_inum.h"
#include "xfs_log.h"
#include "xfs_trans.h"
#include "xfs_sb.h"
#include "xfs_ag.h"
#include "xfs_dir.h"
#include "xfs_dir2.h"
#include "xfs_dmapi.h"
#include "xfs_mount.h"
#include "xfs_clnt.h"
#include "xfs_mountops.h"
#include <geom/geom.h>
#include <geom/geom_vfs.h>
xfs_buf_t *
xfs_buf_read_flags(xfs_buftarg_t *target, xfs_daddr_t blkno, size_t len, int flags)
{
struct buf *bp;
KASSERT((target != NULL), ("got NULL buftarg_t"));
if (bread(target->specvp, blkno, BBTOB(len), NOCRED, &bp)) {
printf("bread failed specvp %p blkno %jd BBTOB(len) %ld\n",
target->specvp, (intmax_t)blkno, (long)BBTOB(len));
bp = NULL;
}
/* not really sure what B_MANAGED really does for us
* maybe we should drop this and just stick with a locked buf
*/
if (flags & B_MANAGED)
bp->b_flags |= B_MANAGED;
xfs_buf_set_target(bp, target);
return (bp);
}
xfs_buf_t *
xfs_buf_get_flags(xfs_buftarg_t *target, xfs_daddr_t blkno, size_t len, int flags)
{
struct buf *bp = NULL;
KASSERT((target != NULL), ("got NULL buftarg_t"));
bp = getblk(target->specvp, blkno, BBTOB(len), 0, 0, 0);
if (bp != NULL)
xfs_buf_set_target(bp, target);
return (bp);
}
xfs_buf_t*
xfs_buf_get_empty(size_t size, xfs_buftarg_t *target)
{
struct buf *bp;
bp = geteblk(0, 0);
if (bp != NULL) {
bp->b_bufsize = size;
bp->b_bcount = size;
BUF_ASSERT_HELD(bp);
xfs_buf_set_target(bp, target);
}
return (bp);
}
xfs_buf_t*
xfs_buf_get_noaddr(size_t len, xfs_buftarg_t *target)
{
struct buf *bp;
if (len >= MAXPHYS)
return (NULL);
bp = geteblk(len, 0);
if (bp != NULL) {
BUF_ASSERT_HELD(bp);
xfs_buf_set_target(bp, target);
}
return (bp);
}
void
xfs_buf_free(xfs_buf_t *bp)
{
bp->b_flags |= B_INVAL;
BUF_KERNPROC(bp); /* ugly hack #1 */
if (bp->b_kvasize == 0) {
bp->b_saveaddr = bp->b_kvabase; /* ugly hack #2 */
bp->b_data = bp->b_saveaddr;
bp->b_bcount = 0;
bp->b_bufsize = 0;
}
brelse(bp);
}
void
xfs_buf_readahead(
xfs_buftarg_t *target,
xfs_daddr_t ioff,
size_t isize,
xfs_buf_flags_t flags)
{
daddr_t rablkno;
int rabsize;
rablkno = ioff;
rabsize = BBTOB(isize);
breada(target->specvp, &rablkno, &rabsize, 1, NOCRED);
}
void
xfs_buf_set_target(xfs_buf_t *bp, xfs_buftarg_t *targ)
{
bp->b_bufobj = &targ->specvp->v_bufobj;
bp->b_caller1 = targ;
}
xfs_buftarg_t *
xfs_buf_get_target(xfs_buf_t *bp)
{
return (xfs_buftarg_t *)bp->b_caller1;
}
int
XFS_bwrite(xfs_buf_t *bp)
{
int error;
if (bp->b_vp == NULL) {
error = xfs_buf_iorequest(bp);
if ((bp->b_flags & B_ASYNC) == 0) {
error = bufwait(bp);
#if 0
if (BUF_LOCKRECURSED(bp))
BUF_UNLOCK(bp);
else
brelse(bp);
#endif
brelse(bp);
}
return (error);
}
error = bwrite(bp);
return (error);
}
void
xfs_buf_pin(xfs_buf_t *bp)
{
bpin(bp);
}
void
xfs_buf_unpin(xfs_buf_t *bp)
{
bunpin(bp);
}
int
xfs_buf_ispin(xfs_buf_t *bp)
{
return bp->b_pin_count;
}
#if 0
void
xfs_buf_wait_unpin(
xfs_buf_t *bp)
{
bunpin_wait(bp);
}
#endif
/*
* Move data into or out of a buffer.
*/
void
xfs_buf_iomove(
xfs_buf_t *bp, /* buffer to process */
size_t boff, /* starting buffer offset */
size_t bsize, /* length to copy */
caddr_t data, /* data address */
xfs_buf_rw_t mode) /* read/write/zero flag */
{
printf("xfs_buf_iomove NI\n");
#ifdef RMC
size_t bend, cpoff, csize;
struct page *page;
bend = boff + bsize;
while (boff < bend) {
page = bp->b_pages[xfs_buf_btoct(boff + bp->b_offset)];
cpoff = xfs_buf_poff(boff + bp->b_offset);
csize = min_t(size_t,
PAGE_CACHE_SIZE-cpoff, bp->b_count_desired-boff);
ASSERT(((csize + cpoff) <= PAGE_CACHE_SIZE));
switch (mode) {
case XBRW_ZERO:
memset(page_address(page) + cpoff, 0, csize);
break;
case XBRW_READ:
memcpy(data, page_address(page) + cpoff, csize);
break;
case XBRW_WRITE:
memcpy(page_address(page) + cpoff, data, csize);
}
boff += csize;
data += csize;
}
#endif
}
/*
* Handling of buffer targets (buftargs).
*/
/*
* Wait for any bufs with callbacks that have been submitted but
* have not yet returned... walk the hash list for the target.
*/
void
xfs_wait_buftarg(
xfs_buftarg_t *bp)
{
printf("xfs_wait_buftarg(%p) NI\n", bp);
}
int
xfs_flush_buftarg(
xfs_buftarg_t *btp,
int wait)
{
int error = 0;
error = vinvalbuf(btp->specvp, V_SAVE | V_NORMAL, 0, 0);
return error;
}
void
xfs_free_buftarg(
xfs_buftarg_t *btp,
int external)
{
xfs_flush_buftarg(btp, /* wait */ 0);
kmem_free(btp, sizeof(*btp));
}
int
xfs_readonly_buftarg(
xfs_buftarg_t *btp)
{
struct g_consumer *cp;
KASSERT(btp->specvp->v_bufobj.bo_ops == &xfs_bo_ops,
("Bogus xfs_buftarg_t pointer"));
cp = btp->specvp->v_bufobj.bo_private;
return (cp->acw == 0);
}
#if 0
void
xfs_relse_buftarg(
xfs_buftarg_t *btp)
{
printf("xfs_relse_buftargNI %p\n",btp);
}
#endif
unsigned int
xfs_getsize_buftarg(
xfs_buftarg_t *btp)
{
struct g_consumer *cp;
cp = btp->specvp->v_bufobj.bo_private;
return (cp->provider->sectorsize);
}
int
xfs_setsize_buftarg(
xfs_buftarg_t *btp,
unsigned int blocksize,
unsigned int sectorsize)
{
printf("xfs_setsize_buftarg NI %p\n",btp);
return 0;
}
xfs_buftarg_t *
xfs_alloc_buftarg(
struct vnode *bdev,
int external)
{
xfs_buftarg_t *btp;
btp = kmem_zalloc(sizeof(*btp), KM_SLEEP);
btp->dev = bdev->v_rdev;
btp->specvp = bdev;
return btp;
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,350 +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_FREEBSD__
#define __XFS_FREEBSD__
#include <xfs_config.h>
#include <xfs_compat.h>
/*
* Some types are conditional depending on the target system.
* XFS_BIG_BLKNOS needs block layer disk addresses to be 64 bits.
* XFS_BIG_INUMS needs the VFS inode number to be 64 bits, as well
* as requiring XFS_BIG_BLKNOS to be set.
*/
#define XFS_BIG_BLKNOS 1
#define XFS_BIG_INUMS 0
#include <xfs_types.h>
#include <xfs_arch.h>
#include <support/atomic.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/rwsem.h>
#include <support/rwlock.h>
#include <support/sema.h>
#include <support/debug.h>
#include <support/move.h>
#include <support/uuid.h>
#include <support/time.h>
#include <xfs_behavior.h>
#include <xfs_cred.h>
#include <xfs_vfs.h>
#include <xfs_vnode.h>
#include <xfs_stats.h>
#include <xfs_sysctl.h>
#include <xfs_iops.h>
#include <xfs_super.h>
#include <xfs_fs_subr.h>
#include <xfs_buf.h>
#include <xfs_frw.h>
/*
* Feature macros (disable/enable)
*/
#undef HAVE_REFCACHE /* Do not use refcache. */
#undef HAVE_SENDFILE /* sendfile(2) is available in FreeBSD. */
#ifndef EVMS_MAJOR
#define EVMS_MAJOR 117
#endif
#define restricted_chown xfs_params.restrict_chown.val
#define irix_sgid_inherit xfs_params.sgid_inherit.val
#define irix_symlink_mode xfs_params.symlink_mode.val
#define xfs_panic_mask xfs_params.panic_mask.val
#define xfs_error_level xfs_params.error_level.val
#define xfs_syncd_centisecs xfs_params.syncd_timer.val
#define xfs_probe_dmapi xfs_params.probe_dmapi.val
#define xfs_probe_ioops xfs_params.probe_ioops.val
#define xfs_probe_quota xfs_params.probe_quota.val
#define xfs_stats_clear xfs_params.stats_clear.val
#define xfs_inherit_sync xfs_params.inherit_sync.val
#define xfs_inherit_nodump xfs_params.inherit_nodump.val
#define xfs_inherit_noatime xfs_params.inherit_noatim.val
#define xfs_buf_timer_centisecs xfs_params.xfs_buf_timer.val
#define xfs_buf_age_centisecs xfs_params.xfs_buf_age.val
#define xfs_inherit_nosymlinks xfs_params.inherit_nosym.val
#define xfs_rotorstep xfs_params.rotorstep.val
#define current_cpu() smp_processor_id()
#define current_pid() (curthread->td_proc->p_pid)
#define NBPP PAGE_SIZE
#define DPPSHFT (PAGE_SHIFT - 9)
#define NDPP (1 << (PAGE_SHIFT - 9))
#define dtop(DD) (((DD) + NDPP - 1) >> DPPSHFT)
#define dtopt(DD) ((DD) >> DPPSHFT)
#define dpoff(DD) ((DD) & (NDPP-1))
#define NBBY 8 /* number of bits per byte */
#define NBPC PAGE_SIZE /* Number of bytes per click */
#define BPCSHIFT PAGE_SHIFT /* LOG2(NBPC) if exact */
/* number of BB's per block device block */
#define BLKDEV_BB BTOBB(BLKDEV_IOSIZE)
/* bytes to clicks */
#define btoct(x) ((__psunsigned_t)(x)>>BPCSHIFT)
#define btoc64(x) (((__uint64_t)(x)+(NBPC-1))>>BPCSHIFT)
#define btoct64(x) ((__uint64_t)(x)>>BPCSHIFT)
#define io_btoc(x) (((__psunsigned_t)(x)+(IO_NBPC-1))>>IO_BPCSHIFT)
#define io_btoct(x) ((__psunsigned_t)(x)>>IO_BPCSHIFT)
/* off_t bytes to clicks */
#define offtoc(x) (((__uint64_t)(x)+(NBPC-1))>>BPCSHIFT)
#define offtoct(x) ((xfs_off_t)(x)>>BPCSHIFT)
/* clicks to off_t bytes */
#define ctooff(x) ((xfs_off_t)(x)<<BPCSHIFT)
/* clicks to bytes */
#define btoct(x) ((__psunsigned_t)(x)>>BPCSHIFT)
#define ctob64(x) ((__uint64_t)(x)<<BPCSHIFT)
#define io_ctob(x) ((__psunsigned_t)(x)<<IO_BPCSHIFT)
#ifndef CELL_CAPABLE
#define FSC_NOTIFY_NAME_CHANGED(vp)
#endif
#ifndef ENOATTR
#define ENOATTR ENODATA /* Attribute not found */
#endif
/* Note: EWRONGFS never visible outside the kernel */
#define EWRONGFS EINVAL /* Mount with wrong filesystem type */
/*
* XXX EFSCORRUPTED needs a real value in errno.h. asm-i386/errno.h won't
* return codes out of its known range in errno.
* XXX Also note: needs to be < 1000 and fairly unique on Linux (mustn't
* conflict with any code we use already or any code a driver may use)
* XXX Some options (currently we do #2):
* 1/ New error code ["Filesystem is corrupted", _after_ glibc updated]
* 2/ 990 ["Unknown error 990"]
* 3/ EUCLEAN ["Structure needs cleaning"]
* 4/ Convert EFSCORRUPTED to EIO [just prior to return into userspace]
*/
#define EFSCORRUPTED 990 /* Filesystem is corrupted */
#define SYNCHRONIZE() __compiler_membar()
#define __return_address __builtin_return_address(0)
/*
* IRIX (BSD) quotactl makes use of separate commands for user/group,
* whereas on Linux the syscall encodes this information into the cmd
* field (see the QCMD macro in quota.h). These macros help keep the
* code portable - they are not visible from the syscall interface.
*/
#define Q_XSETGQLIM XQM_CMD(0x8) /* set groups disk limits */
#define Q_XGETGQUOTA XQM_CMD(0x9) /* get groups disk limits */
/* IRIX uses a dynamic sizing algorithm (ndquot = 200 + numprocs*2) */
/* we may well need to fine-tune this if it ever becomes an issue. */
#define DQUOT_MAX_HEURISTIC 1024 /* NR_DQUOTS */
#define ndquot DQUOT_MAX_HEURISTIC
/* IRIX uses the current size of the name cache to guess a good value */
/* - this isn't the same but is a good enough starting point for now. */
#define DQUOT_HASH_HEURISTIC files_stat.nr_files
/* IRIX inodes maintain the project ID also, zero this field on Linux */
#define DEFAULT_PROJID 0
#define dfltprid DEFAULT_PROJID
#define FINVIS 0x0102 /* don't update timestamps - XFS */
#define howmany(x, y) (((x)+((y)-1))/(y))
#define roundup(x, y) ((((x)+((y)-1))/(y))*(y))
#define xfs_sort(a,n,s,fn) qsort(a,n,s,fn)
static inline int xfs_itruncate_data(void *ip, xfs_off_t off) {
printf ("xfs_itruncate_data NI\n");
return 0;
}
/*
* Juggle IRIX device numbers - still used in ondisk structures
*/
#define XFS_DEV_BITSMAJOR 14
#define XFS_DEV_BITSMINOR 18
#define XFS_DEV_MAXMAJ 0x1ff
#define XFS_DEV_MAXMIN 0x3ffff
#define XFS_DEV_MAJOR(dev) ((int)(((unsigned)(dev)>>XFS_DEV_BITSMINOR) \
& XFS_DEV_MAXMAJ))
#define XFS_DEV_MINOR(dev) ((int)((dev)&XFS_DEV_MAXMIN))
#define XFS_MKDEV(major,minor) ((xfs_dev_t)(((major)<<XFS_DEV_BITSMINOR) \
| (minor&XFS_DEV_MAXMIN)))
#define XFS_DEV_TO_KDEVT(dev) mk_kdev(XFS_DEV_MAJOR(dev),XFS_DEV_MINOR(dev))
/* Produce a kernel stack trace */
static inline void xfs_stack_trace(void)
{
kdb_backtrace();
}
#define xfs_statvfs_fsid(statp, mp) \
({ \
(statp)->f_fsid.val[0] = /*dev2udev(mp->m_dev) */ 1; \
(statp)->f_fsid.val[1] = 0; \
})
/* Move the kernel do_div definition off to one side */
#if defined __i386__
/* For ia32 we need to pull some tricks to get past various versions
* of the compiler which do not like us using do_div in the middle
* of large functions.
*/
static inline __u32 xfs_do_div(void *a, __u32 b, int n)
{
__u32 mod;
switch (n) {
case 4:
mod = *(__u32 *)a % b;
*(__u32 *)a = *(__u32 *)a / b;
return mod;
case 8:
{
unsigned long __upper, __low, __high, __mod;
__u64 c = *(__u64 *)a;
__upper = __high = c >> 32;
__low = c;
if (__high) {
__upper = __high % (b);
__high = __high / (b);
}
asm("divl %2":"=a" (__low), "=d" (__mod):"rm" (b), "0" (__low), "1" (__upper));
asm("":"=A" (c):"a" (__low),"d" (__high));
*(__u64 *)a = c;
return __mod;
}
}
/* NOTREACHED */
return 0;
}
/* Side effect free 64 bit mod operation */
static inline __u32 xfs_do_mod(void *a, __u32 b, int n)
{
switch (n) {
case 4:
return *(__u32 *)a % b;
case 8:
{
unsigned long __upper, __low, __high, __mod;
__u64 c = *(__u64 *)a;
__upper = __high = c >> 32;
__low = c;
if (__high) {
__upper = __high % (b);
__high = __high / (b);
}
asm("divl %2":"=a" (__low), "=d" (__mod):"rm" (b), "0" (__low), "1" (__upper));
asm("":"=A" (c):"a" (__low),"d" (__high));
return __mod;
}
}
/* NOTREACHED */
return 0;
}
#else
#define do_div(n, base) ({\
int __res; \
__res = ((__u64)(n)) % (__u32)(base); \
(n) = ((__u64)(n)) / (__u32)(base); \
__res; })
static inline __u32 xfs_do_div(void *a, __u32 b, int n)
{
__u32 mod;
switch (n) {
case 4:
mod = *(__u32 *)a % b;
*(__u32 *)a = *(__u32 *)a / b;
return mod;
case 8:
mod = do_div(*(__u64 *)a, b);
return mod;
}
/* NOTREACHED */
return 0;
}
/* Side effect free 64 bit mod operation */
static inline __u32 xfs_do_mod(void *a, __u32 b, int n)
{
switch (n) {
case 4:
return *(__u32 *)a % b;
case 8:
{
__u64 c = *(__u64 *)a;
return do_div(c, b);
}
}
/* NOTREACHED */
return 0;
}
#endif
#undef do_div
#define do_div(a, b) xfs_do_div(&(a), (b), sizeof(a))
#define do_mod(a, b) xfs_do_mod(&(a), (b), sizeof(a))
static inline __uint64_t roundup_64(__uint64_t x, __uint32_t y)
{
x += y - 1;
do_div(x, y);
return(x * y);
}
#endif /* __XFS_FREEBSD__ */

View File

@ -1,419 +0,0 @@
/*
* Copyright (c) 2000-2003 Silicon Graphics, Inc. All Rights Reserved.
* Copyright (c) 2006 Russell Cattelan Digital Elves, 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.h"
#include "xfs_types.h"
#include "xfs_bit.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_alloc_btree.h"
#include "xfs_bmap_btree.h"
#include "xfs_ialloc_btree.h"
#include "xfs_attr_sf.h"
#include "xfs_dir_sf.h"
#include "xfs_dir2_sf.h"
#include "xfs_dinode.h"
#include "xfs_inode.h"
#include "xfs_btree.h"
#include "xfs_ialloc.h"
#include "xfs_quota.h"
#include "xfs_utils.h"
#include "xfs_vnode.h"
static int xfs_vn_allocate(xfs_mount_t *, xfs_inode_t *, struct xfs_vnode **);
/*
* Look up an inode by number in the given file system.
* The inode is looked up in the hash table for the file system
* represented by the mount point parameter mp. Each bucket of
* the hash table is guarded by an individual semaphore.
*
* If the inode is found in the hash table, its corresponding vnode
* is obtained with a call to vn_get(). This call takes care of
* coordination with the reclamation of the inode and vnode. Note
* that the vmap structure is filled in while holding the hash lock.
* This gives us the state of the inode/vnode when we found it and
* is used for coordination in vn_get().
*
* If it is not in core, read it in from the file system's device and
* add the inode into the hash table.
*
* The inode is locked according to the value of the lock_flags parameter.
* This flag parameter indicates how and if the inode's IO lock and inode lock
* should be taken.
*
* mp -- the mount point structure for the current file system. It points
* to the inode hash table.
* tp -- a pointer to the current transaction if there is one. This is
* simply passed through to the xfs_iread() call.
* ino -- the number of the inode desired. This is the unique identifier
* within the file system for the inode being requested.
* lock_flags -- flags indicating how to lock the inode. See the comment
* for xfs_ilock() for a list of valid values.
* bno -- the block number starting the buffer containing the inode,
* if known (as by bulkstat), else 0.
*/
int
xfs_iget(
xfs_mount_t *mp,
xfs_trans_t *tp,
xfs_ino_t ino,
uint flags,
uint lock_flags,
xfs_inode_t **ipp,
xfs_daddr_t bno)
{
xfs_ihash_t *ih;
xfs_inode_t *ip;
xfs_inode_t *iq;
xfs_vnode_t *vp;
ulong version;
int error;
/* REFERENCED */
int newnode;
xfs_chash_t *ch;
xfs_chashlist_t *chl, *chlnew;
vmap_t vmap;
SPLDECL(s);
XFS_STATS_INC(xs_ig_attempts);
ih = XFS_IHASH(mp, ino);
again:
read_lock(&ih->ih_lock);
for (ip = ih->ih_next; ip != NULL; ip = ip->i_next) {
if (ip->i_ino == ino) {
vp = XFS_ITOV(ip);
VMAP(vp, vmap);
/*
* Inode cache hit: if ip is not at the front of
* its hash chain, move it there now.
* Do this with the lock held for update, but
* do statistics after releasing the lock.
*/
if (ip->i_prevp != &ih->ih_next
&& rwlock_trypromote(&ih->ih_lock)) {
if ((iq = ip->i_next)) {
iq->i_prevp = ip->i_prevp;
}
*ip->i_prevp = iq;
iq = ih->ih_next;
iq->i_prevp = &ip->i_next;
ip->i_next = iq;
ip->i_prevp = &ih->ih_next;
ih->ih_next = ip;
write_unlock(&ih->ih_lock);
} else {
read_unlock(&ih->ih_lock);
}
XFS_STATS_INC(xs_ig_found);
/*
* Get a reference to the vnode/inode.
* vn_get() takes care of coordination with
* the file system inode release and reclaim
* functions. If it returns NULL, the inode
* has been reclaimed so just start the search
* over again. We probably won't find it,
* but we could be racing with another cpu
* looking for the same inode so we have to at
* least look.
*/
if (!(vp = vn_get(vp, &vmap))) {
XFS_STATS_INC(xs_ig_frecycle);
goto again;
}
if (lock_flags != 0) {
ip->i_flags &= ~XFS_IRECLAIM;
xfs_ilock(ip, lock_flags);
}
newnode = (ip->i_d.di_mode == 0);
if (newnode) {
xfs_iocore_inode_reinit(ip);
}
ip->i_flags &= ~XFS_ISTALE;
vn_trace_exit(vp, "xfs_iget.found",
(inst_t *)__return_address);
goto return_ip;
}
}
/*
* Inode cache miss: save the hash chain version stamp and unlock
* the chain, so we don't deadlock in vn_alloc.
*/
XFS_STATS_INC(xs_ig_missed);
version = ih->ih_version;
read_unlock(&ih->ih_lock);
/*
* Read the disk inode attributes into a new inode structure and get
* a new vnode for it. This should also initialize i_ino and i_mount.
*/
error = xfs_iread(mp, tp, ino, &ip, bno);
if (error) {
return error;
}
error = xfs_vn_allocate(mp, ip, &vp);
if (error) {
return error;
}
vn_trace_exit(vp, "xfs_iget.alloc", (inst_t *)__return_address);
xfs_inode_lock_init(ip, vp);
xfs_iocore_inode_init(ip);
if (lock_flags != 0) {
xfs_ilock(ip, lock_flags);
}
/*
* Put ip on its hash chain, unless someone else hashed a duplicate
* after we released the hash lock.
*/
write_lock(&ih->ih_lock);
if (ih->ih_version != version) {
for (iq = ih->ih_next; iq != NULL; iq = iq->i_next) {
if (iq->i_ino == ino) {
write_unlock(&ih->ih_lock);
xfs_idestroy(ip);
XFS_STATS_INC(xs_ig_dup);
goto again;
}
}
}
/*
* These values _must_ be set before releasing ihlock!
*/
ip->i_hash = ih;
if ((iq = ih->ih_next)) {
iq->i_prevp = &ip->i_next;
}
ip->i_next = iq;
ip->i_prevp = &ih->ih_next;
ih->ih_next = ip;
ip->i_udquot = ip->i_gdquot = NULL;
ih->ih_version++;
write_unlock(&ih->ih_lock);
/*
* put ip on its cluster's hash chain
*/
ASSERT(ip->i_chash == NULL && ip->i_cprev == NULL &&
ip->i_cnext == NULL);
chlnew = NULL;
ch = XFS_CHASH(mp, ip->i_blkno);
chlredo:
s = mutex_spinlock(&ch->ch_lock);
for (chl = ch->ch_list; chl != NULL; chl = chl->chl_next) {
if (chl->chl_blkno == ip->i_blkno) {
/* insert this inode into the doubly-linked list
* where chl points */
if ((iq = chl->chl_ip)) {
ip->i_cprev = iq->i_cprev;
iq->i_cprev->i_cnext = ip;
iq->i_cprev = ip;
ip->i_cnext = iq;
} else {
ip->i_cnext = ip;
ip->i_cprev = ip;
}
chl->chl_ip = ip;
ip->i_chash = chl;
break;
}
}
/* no hash list found for this block; add a new hash list */
if (chl == NULL) {
if (chlnew == NULL) {
mutex_spinunlock(&ch->ch_lock, s);
ASSERT(xfs_chashlist_zone != NULL);
chlnew = (xfs_chashlist_t *)
kmem_zone_alloc(xfs_chashlist_zone,
KM_SLEEP);
ASSERT(chlnew != NULL);
goto chlredo;
} else {
ip->i_cnext = ip;
ip->i_cprev = ip;
ip->i_chash = chlnew;
chlnew->chl_ip = ip;
chlnew->chl_blkno = ip->i_blkno;
chlnew->chl_next = ch->ch_list;
ch->ch_list = chlnew;
chlnew = NULL;
}
} else {
if (chlnew != NULL) {
kmem_zone_free(xfs_chashlist_zone, chlnew);
}
}
mutex_spinunlock(&ch->ch_lock, s);
/*
* Link ip to its mount and thread it on the mount's inode list.
*/
XFS_MOUNT_ILOCK(mp);
if ((iq = mp->m_inodes)) {
ASSERT(iq->i_mprev->i_mnext == iq);
ip->i_mprev = iq->i_mprev;
iq->i_mprev->i_mnext = ip;
iq->i_mprev = ip;
ip->i_mnext = iq;
} else {
ip->i_mnext = ip;
ip->i_mprev = ip;
}
mp->m_inodes = ip;
XFS_MOUNT_IUNLOCK(mp);
newnode = 1;
return_ip:
ASSERT(ip->i_df.if_ext_max ==
XFS_IFORK_DSIZE(ip) / sizeof(xfs_bmbt_rec_t));
ASSERT(((ip->i_d.di_flags & XFS_DIFLAG_REALTIME) != 0) ==
((ip->i_iocore.io_flags & XFS_IOCORE_RT) != 0));
*ipp = ip;
/*
* If we have a real type for an on-disk inode, we can set ops(&unlock)
* now. If it's a new inode being created, xfs_ialloc will handle it.
*/
XVFS_INIT_VNODE(XFS_MTOVFS(mp), vp, XFS_ITOBHV(ip), 1);
return 0;
}
/*
* Special iput for brand-new inodes that are still locked
*/
void
xfs_iput_new(xfs_inode_t *ip,
uint lock_flags)
{
xfs_vnode_t *vp = XFS_ITOV(ip);
vn_trace_entry(vp, "xfs_iput_new", (inst_t *)__return_address);
printf("xfs_iput_new: ip %p\n",ip);
if ((ip->i_d.di_mode == 0)) {
ASSERT(!(ip->i_flags & XFS_IRECLAIMABLE));
//vn_mark_bad(vp);
printf("xfs_iput_new: ip %p di_mode == 0\n",ip);
/* mabe call vgone here? RMC */
}
if (lock_flags)
xfs_iunlock(ip, lock_flags);
ASSERT_VOP_LOCKED(vp->v_vnode, "xfs_iput_new");
vput(vp->v_vnode);
}
extern struct vop_vector xfs_vnops;
static int
xfs_vn_allocate(xfs_mount_t *mp, xfs_inode_t *ip, struct xfs_vnode **vpp)
{
struct vnode *vp;
struct xfs_vnode *vdata;
int error;
/* Use zone allocator here? */
vdata = kmem_zalloc(sizeof(*vdata), KM_SLEEP);
error = getnewvnode("xfs", XVFSTOMNT(XFS_MTOVFS(mp)),
&xfs_vnops, &vp);
if (error) {
kmem_free(vdata, sizeof(*vdata));
return (error);
}
vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
VN_LOCK_AREC(vp);
error = insmntque(vp, XVFSTOMNT(XFS_MTOVFS(mp)));
if (error != 0) {
kmem_free(vdata, sizeof(*vdata));
return (error);
}
vp->v_data = (void *)vdata;
vdata->v_number= 0;
vdata->v_inode = ip;
vdata->v_vfsp = XFS_MTOVFS(mp);
vdata->v_vnode = vp;
vn_bhv_head_init(VN_BHV_HEAD(vdata), "vnode");
#ifdef CONFIG_XFS_VNODE_TRACING
vp->v_trace = ktrace_alloc(VNODE_TRACE_SIZE, KM_SLEEP);
#endif /* CONFIG_XFS_VNODE_TRACING */
vn_trace_exit(vp, "vn_initialize", (inst_t *)__return_address);
if (error == 0)
*vpp = vdata;
return (error);
}

View File

@ -1,891 +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"
#include "xfs_fs.h"
#include "xfs_bit.h"
#include "xfs_log.h"
#include "xfs_inum.h"
#include "xfs_trans.h"
#include "xfs_sb.h"
#include "xfs_ag.h"
#include "xfs_dir.h"
#include "xfs_dir2.h"
#include "xfs_alloc.h"
#include "xfs_dmapi.h"
#include "xfs_quota.h"
#include "xfs_mount.h"
#include "xfs_bmap_btree.h"
#include "xfs_alloc_btree.h"
#include "xfs_ialloc_btree.h"
#include "xfs_dir_sf.h"
#include "xfs_dir2_sf.h"
#include "xfs_attr_sf.h"
#include "xfs_dinode.h"
#include "xfs_inode.h"
#include "xfs_bmap.h"
#include "xfs_btree.h"
#include "xfs_ialloc.h"
#include "xfs_rtalloc.h"
#include "xfs_error.h"
#include "xfs_itable.h"
#include "xfs_rw.h"
#include "xfs_acl.h"
#include "xfs_cap.h"
#include "xfs_mac.h"
#include "xfs_attr.h"
#include "xfs_inode_item.h"
#include "xfs_buf_item.h"
#include "xfs_utils.h"
#include "xfs_iomap.h"
#if defined(XFS_RW_TRACE)
void
xfs_rw_enter_trace(
int tag,
xfs_iocore_t *io,
const char *buf,
size_t size,
loff_t offset,
int ioflags)
{
xfs_inode_t *ip = XFS_IO_INODE(io);
if (ip->i_rwtrace == NULL)
return;
ktrace_enter(ip->i_rwtrace,
(void *)(unsigned long)tag,
(void *)ip,
(void *)((unsigned long)((ip->i_d.di_size >> 32) & 0xffffffff)),
(void *)((unsigned long)(ip->i_d.di_size & 0xffffffff)),
(void *)(__psint_t)buf,
(void *)((unsigned long)size),
(void *)((unsigned long)((offset >> 32) & 0xffffffff)),
(void *)((unsigned long)(offset & 0xffffffff)),
(void *)((unsigned long)ioflags),
(void *)((unsigned long)((io->io_new_size >> 32) & 0xffffffff)),
(void *)((unsigned long)(io->io_new_size & 0xffffffff)),
(void *)NULL,
(void *)NULL,
(void *)NULL,
(void *)NULL,
(void *)NULL);
}
void
xfs_inval_cached_trace(
xfs_iocore_t *io,
xfs_off_t offset,
xfs_off_t len,
xfs_off_t first,
xfs_off_t last)
{
xfs_inode_t *ip = XFS_IO_INODE(io);
if (ip->i_rwtrace == NULL)
return;
ktrace_enter(ip->i_rwtrace,
(void *)(__psint_t)XFS_INVAL_CACHED,
(void *)ip,
(void *)((unsigned long)((offset >> 32) & 0xffffffff)),
(void *)((unsigned long)(offset & 0xffffffff)),
(void *)((unsigned long)((len >> 32) & 0xffffffff)),
(void *)((unsigned long)(len & 0xffffffff)),
(void *)((unsigned long)((first >> 32) & 0xffffffff)),
(void *)((unsigned long)(first & 0xffffffff)),
(void *)((unsigned long)((last >> 32) & 0xffffffff)),
(void *)((unsigned long)(last & 0xffffffff)),
(void *)NULL,
(void *)NULL,
(void *)NULL,
(void *)NULL,
(void *)NULL,
(void *)NULL);
}
#endif
/*
* xfs_iozero
*
* xfs_iozero clears the specified range of buffer supplied,
* and marks all the affected blocks as valid and modified. If
* an affected block is not allocated, it will be allocated. If
* an affected block is not completely overwritten, and is not
* valid before the operation, it will be read from disk before
* being partially zeroed.
*/
STATIC int
xfs_iozero(
xfs_vnode_t *vp, /* vnode */
xfs_off_t pos, /* offset in file */
size_t count, /* size of data to zero */
xfs_off_t end_size) /* max file size to set */
{
int status;
status = 0; /* XXXKAN: */
#ifdef XXXKAN
unsigned bytes;
struct page *page;
struct address_space *mapping;
char *kaddr;
mapping = ip->i_mapping;
do {
unsigned long index, offset;
offset = (pos & (PAGE_CACHE_SIZE -1)); /* Within page */
index = pos >> PAGE_CACHE_SHIFT;
bytes = PAGE_CACHE_SIZE - offset;
if (bytes > count)
bytes = count;
status = -ENOMEM;
page = grab_cache_page(mapping, index);
if (!page)
break;
kaddr = kmap(page);
status = mapping->a_ops->prepare_write(NULL, page, offset,
offset + bytes);
if (status) {
goto unlock;
}
memset((void *) (kaddr + offset), 0, bytes);
flush_dcache_page(page);
status = mapping->a_ops->commit_write(NULL, page, offset,
offset + bytes);
if (!status) {
pos += bytes;
count -= bytes;
if (pos > i_size_read(ip))
i_size_write(ip, pos < end_size ? pos : end_size);
}
unlock:
kunmap(page);
unlock_page(page);
page_cache_release(page);
if (status)
break;
} while (count);
#endif
return (-status);
}
ssize_t /* bytes read, or (-) error */
xfs_read(
bhv_desc_t *bdp,
uio_t *uio,
int ioflags,
cred_t *credp)
{
ssize_t ret, size;
xfs_fsize_t n;
xfs_inode_t *ip;
xfs_mount_t *mp;
ip = XFS_BHVTOI(bdp);
mp = ip->i_mount;
XFS_STATS_INC(xs_read_calls);
if (unlikely(ioflags & IO_ISDIRECT)) {
if (((__psint_t)buf & BBMASK) ||
(uio->uio_offset & mp->m_blockmask) ||
(uio->uio_resid & mp->m_blockmask)) {
if (uio->uio_offset >= ip->i_d.di_size) {
return (0);
}
return EINVAL;
}
}
if (uio->uio_resid == 0)
return 0;
n = XFS_MAXIOFFSET(mp) - uio->uio_offset;
if (n <= 0)
return EFBIG;
size = (n < uio->uio_resid)? n : uio->uio_resid;
if (XFS_FORCED_SHUTDOWN(mp)) {
return EIO;
}
xfs_ilock(ip, XFS_IOLOCK_SHARED);
#ifdef XXX
if (DM_EVENT_ENABLED(BHV_TO_VNODE(bdp)->v_vfsp, ip, DM_EVENT_READ) &&
!(ioflags & IO_INVIS)) {
int error;
vrwlock_t locktype = VRWLOCK_READ;
int dmflags = FILP_DELAY_FLAG(file) | DM_SEM_FLAG_RD(ioflags);
error = XFS_SEND_DATA(mp, DM_EVENT_READ, BHV_TO_VNODE(bdp),
uio->uio_offset, size, dmflags, &locktype);
if (error) {
xfs_iunlock(ip, XFS_IOLOCK_SHARED);
return (error);
}
}
#endif
ret = xfs_read_file(mp, ip, uio, ioflags);
xfs_iunlock(ip, XFS_IOLOCK_SHARED);
XFS_STATS_ADD(xs_read_bytes, ret);
if (likely((ioflags & IO_INVIS) == 0)) {
xfs_ichgtime(ip, XFS_ICHGTIME_ACC);
}
return ret;
}
/*
* This routine is called to handle zeroing any space in the last
* block of the file that is beyond the EOF. We do this since the
* size is being increased without writing anything to that block
* and we don't want anyone to read the garbage on the disk.
*/
STATIC int /* error (positive) */
xfs_zero_last_block(
xfs_vnode_t *vp,
xfs_iocore_t *io,
xfs_fsize_t isize,
xfs_fsize_t end_size)
{
xfs_fileoff_t last_fsb;
xfs_mount_t *mp;
int nimaps;
int zero_offset;
int zero_len;
int error = 0;
xfs_bmbt_irec_t imap;
xfs_off_t loff;
ASSERT(ismrlocked(io->io_lock, MR_UPDATE) != 0);
mp = io->io_mount;
zero_offset = XFS_B_FSB_OFFSET(mp, isize);
if (zero_offset == 0) {
/*
* There are no extra bytes in the last block on disk to
* zero, so return.
*/
return 0;
}
last_fsb = XFS_B_TO_FSBT(mp, isize);
nimaps = 1;
error = XFS_BMAPI(mp, NULL, io, last_fsb, 1, 0, NULL, 0, &imap,
&nimaps, NULL, NULL);
if (error) {
return error;
}
ASSERT(nimaps > 0);
/*
* If the block underlying isize is just a hole, then there
* is nothing to zero.
*/
if (imap.br_startblock == HOLESTARTBLOCK) {
return 0;
}
/*
* Zero the part of the last block beyond the EOF, and write it
* out sync. We need to drop the ilock while we do this so we
* don't deadlock when the buffer cache calls back to us.
*/
XFS_IUNLOCK(mp, io, XFS_ILOCK_EXCL| XFS_EXTSIZE_RD);
loff = XFS_FSB_TO_B(mp, last_fsb);
zero_len = mp->m_sb.sb_blocksize - zero_offset;
error = xfs_iozero(vp, loff + zero_offset, zero_len, end_size);
XFS_ILOCK(mp, io, XFS_ILOCK_EXCL|XFS_EXTSIZE_RD);
ASSERT(error >= 0);
return error;
}
/*
* Zero any on disk space between the current EOF and the new,
* larger EOF. This handles the normal case of zeroing the remainder
* of the last block in the file and the unusual case of zeroing blocks
* out beyond the size of the file. This second case only happens
* with fixed size extents and when the system crashes before the inode
* size was updated but after blocks were allocated. If fill is set,
* then any holes in the range are filled and zeroed. If not, the holes
* are left alone as holes.
*/
int /* error (positive) */
xfs_zero_eof(
xfs_vnode_t *vp,
xfs_iocore_t *io,
xfs_off_t offset, /* starting I/O offset */
xfs_fsize_t isize, /* current inode size */
xfs_fsize_t end_size) /* terminal inode size */
{
xfs_fileoff_t start_zero_fsb;
xfs_fileoff_t end_zero_fsb;
xfs_fileoff_t zero_count_fsb;
xfs_fileoff_t last_fsb;
xfs_extlen_t buf_len_fsb;
xfs_mount_t *mp;
int nimaps;
int error = 0;
xfs_bmbt_irec_t imap;
ASSERT(ismrlocked(io->io_lock, MR_UPDATE));
ASSERT(ismrlocked(io->io_iolock, MR_UPDATE));
ASSERT(offset > isize);
mp = io->io_mount;
/*
* First handle zeroing the block on which isize resides.
* We only zero a part of that block so it is handled specially.
*/
error = xfs_zero_last_block(vp, io, isize, end_size);
if (error) {
ASSERT(ismrlocked(io->io_lock, MR_UPDATE));
ASSERT(ismrlocked(io->io_iolock, MR_UPDATE));
return error;
}
/*
* Calculate the range between the new size and the old
* where blocks needing to be zeroed may exist. To get the
* block where the last byte in the file currently resides,
* we need to subtract one from the size and truncate back
* to a block boundary. We subtract 1 in case the size is
* exactly on a block boundary.
*/
last_fsb = isize ? XFS_B_TO_FSBT(mp, isize - 1) : (xfs_fileoff_t)-1;
start_zero_fsb = XFS_B_TO_FSB(mp, (xfs_ufsize_t)isize);
end_zero_fsb = XFS_B_TO_FSBT(mp, offset - 1);
ASSERT((xfs_sfiloff_t)last_fsb < (xfs_sfiloff_t)start_zero_fsb);
if (last_fsb == end_zero_fsb) {
/*
* The size was only incremented on its last block.
* We took care of that above, so just return.
*/
return 0;
}
ASSERT(start_zero_fsb <= end_zero_fsb);
while (start_zero_fsb <= end_zero_fsb) {
nimaps = 1;
zero_count_fsb = end_zero_fsb - start_zero_fsb + 1;
error = XFS_BMAPI(mp, NULL, io, start_zero_fsb, zero_count_fsb,
0, NULL, 0, &imap, &nimaps, NULL, NULL);
if (error) {
ASSERT(ismrlocked(io->io_lock, MR_UPDATE));
ASSERT(ismrlocked(io->io_iolock, MR_UPDATE));
return error;
}
ASSERT(nimaps > 0);
if (imap.br_state == XFS_EXT_UNWRITTEN ||
imap.br_startblock == HOLESTARTBLOCK) {
/*
* This loop handles initializing pages that were
* partially initialized by the code below this
* loop. It basically zeroes the part of the page
* that sits on a hole and sets the page as P_HOLE
* and calls remapf if it is a mapped file.
*/
start_zero_fsb = imap.br_startoff + imap.br_blockcount;
ASSERT(start_zero_fsb <= (end_zero_fsb + 1));
continue;
}
/*
* There are blocks in the range requested.
* Zero them a single write at a time. We actually
* don't zero the entire range returned if it is
* too big and simply loop around to get the rest.
* That is not the most efficient thing to do, but it
* is simple and this path should not be exercised often.
*/
buf_len_fsb = XFS_FILBLKS_MIN(imap.br_blockcount,
mp->m_writeio_blocks << 8);
/*
* Drop the inode lock while we're doing the I/O.
* We'll still have the iolock to protect us.
*/
XFS_IUNLOCK(mp, io, XFS_ILOCK_EXCL|XFS_EXTSIZE_RD);
error = xfs_iozero(vp,
XFS_FSB_TO_B(mp, start_zero_fsb),
XFS_FSB_TO_B(mp, buf_len_fsb),
end_size);
if (error) {
goto out_lock;
}
start_zero_fsb = imap.br_startoff + buf_len_fsb;
ASSERT(start_zero_fsb <= (end_zero_fsb + 1));
XFS_ILOCK(mp, io, XFS_ILOCK_EXCL|XFS_EXTSIZE_RD);
}
return 0;
out_lock:
XFS_ILOCK(mp, io, XFS_ILOCK_EXCL|XFS_EXTSIZE_RD);
ASSERT(error >= 0);
return error;
}
ssize_t /* bytes written, or (-) error */
xfs_write(
bhv_desc_t *bdp,
uio_t *uio,
int ioflag,
cred_t *credp)
{
xfs_inode_t *xip;
xfs_mount_t *mp;
ssize_t ret = 0;
int error = 0;
xfs_fsize_t isize, new_size;
xfs_fsize_t n, limit;
xfs_fsize_t size;
xfs_iocore_t *io;
xfs_vnode_t *vp;
int iolock;
//int eventsent = 0;
vrwlock_t locktype;
xfs_off_t offset_c;
xfs_off_t *offset;
xfs_off_t pos;
XFS_STATS_INC(xs_write_calls);
vp = BHV_TO_VNODE(bdp);
xip = XFS_BHVTOI(bdp);
io = &xip->i_iocore;
mp = io->io_mount;
if (XFS_FORCED_SHUTDOWN(xip->i_mount)) {
return EIO;
}
size = uio->uio_resid;
pos = offset_c = uio->uio_offset;
offset = &offset_c;
if (unlikely(ioflag & IO_ISDIRECT)) {
if (((__psint_t)buf & BBMASK) ||
(*offset & mp->m_blockmask) ||
(size & mp->m_blockmask)) {
return EINVAL;
}
iolock = XFS_IOLOCK_SHARED;
locktype = VRWLOCK_WRITE_DIRECT;
} else {
if (io->io_flags & XFS_IOCORE_RT)
return EINVAL;
iolock = XFS_IOLOCK_EXCL;
locktype = VRWLOCK_WRITE;
}
iolock = XFS_IOLOCK_EXCL;
locktype = VRWLOCK_WRITE;
xfs_ilock(xip, XFS_ILOCK_EXCL|iolock);
isize = xip->i_d.di_size;
limit = XFS_MAXIOFFSET(mp);
if (ioflag & O_APPEND)
*offset = isize;
//start:
n = limit - *offset;
if (n <= 0) {
xfs_iunlock(xip, XFS_ILOCK_EXCL|iolock);
return EFBIG;
}
if (n < size)
size = n;
new_size = *offset + size;
if (new_size > isize) {
io->io_new_size = new_size;
}
#ifdef RMC
/* probably be a long time before if ever that we do dmapi */
if ((DM_EVENT_ENABLED(vp->v_vfsp, xip, DM_EVENT_WRITE) &&
!(ioflags & IO_INVIS) && !eventsent)) {
loff_t savedsize = *offset;
int dmflags = FILP_DELAY_FLAG(file) | DM_SEM_FLAG_RD(ioflags);
xfs_iunlock(xip, XFS_ILOCK_EXCL);
error = XFS_SEND_DATA(xip->i_mount, DM_EVENT_WRITE, vp,
*offset, size,
dmflags, &locktype);
if (error) {
if (iolock) xfs_iunlock(xip, iolock);
return -error;
}
xfs_ilock(xip, XFS_ILOCK_EXCL);
eventsent = 1;
/*
* The iolock was dropped and reaquired in XFS_SEND_DATA
* so we have to recheck the size when appending.
* We will only "goto start;" once, since having sent the
* event prevents another call to XFS_SEND_DATA, which is
* what allows the size to change in the first place.
*/
if ((file->f_flags & O_APPEND) &&
savedsize != xip->i_d.di_size) {
*offset = isize = xip->i_d.di_size;
goto start;
}
}
#endif
/*
* If the offset is beyond the size of the file, we have a couple
* of things to do. First, if there is already space allocated
* we need to either create holes or zero the disk or ...
*
* If there is a page where the previous size lands, we need
* to zero it out up to the new size.
*/
if (!(ioflag & IO_ISDIRECT) && (*offset > isize && isize)) {
error = xfs_zero_eof(BHV_TO_VNODE(bdp), io, *offset,
isize, *offset + size);
if (error) {
xfs_iunlock(xip, XFS_ILOCK_EXCL|iolock);
return(-error);
}
}
xfs_iunlock(xip, XFS_ILOCK_EXCL);
#if 0
/*
* If we're writing the file then make sure to clear the
* setuid and setgid bits if the process is not being run
* by root. This keeps people from modifying setuid and
* setgid binaries.
*/
if (((xip->i_d.di_mode & S_ISUID) ||
((xip->i_d.di_mode & (S_ISGID | S_IXGRP)) ==
(S_ISGID | S_IXGRP))) &&
!capable(CAP_FSETID)) {
error = xfs_write_clear_setuid(xip);
if (likely(!error))
error = -remove_suid(file->f_dentry);
if (unlikely(error)) {
xfs_iunlock(xip, iolock);
goto out_unlock_mutex;
}
}
#endif
//retry:
if (unlikely(ioflag & IO_ISDIRECT)) {
#ifdef RMC
xfs_off_t pos = *offset;
struct address_space *mapping = file->f_dentry->d_inode->i_mapping;
struct inode *inode = mapping->host;
ret = precheck_file_write(file, inode, &size, &pos);
if (ret || size == 0)
goto error;
xfs_inval_cached_pages(vp, io, pos, 1, 1);
inode->i_ctime = inode->i_mtime = CURRENT_TIME;
/* mark_inode_dirty_sync(inode); - we do this later */
xfs_rw_enter_trace(XFS_DIOWR_ENTER, io, buf, size, pos, ioflags);
ret = generic_file_direct_IO(WRITE, file, (char *)buf, size, pos);
xfs_inval_cached_pages(vp, io, pos, 1, 1);
if (ret > 0)
*offset += ret;
#endif
} else {
xfs_rw_enter_trace(XFS_WRITE_ENTER, io, buf, size, *offset, ioflags);
ret = xfs_write_file(xip,uio,ioflag);
}
xfs_ichgtime(xip, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
//error:
if (ret <= 0) {
if (iolock)
xfs_rwunlock(bdp, locktype);
return ret;
}
XFS_STATS_ADD(xs_write_bytes, ret);
if (*offset > xip->i_d.di_size) {
xfs_ilock(xip, XFS_ILOCK_EXCL);
if (*offset > xip->i_d.di_size) {
printf("xfs_write look at doing more here %s:%d\n",__FILE__,__LINE__);
#ifdef RMC
struct inode *inode = LINVFS_GET_IP(vp);
i_size_write(inode, *offset);
mark_inode_dirty_sync(inode);
#endif
xip->i_d.di_size = *offset;
xip->i_update_core = 1;
xip->i_update_size = 1;
}
xfs_iunlock(xip, XFS_ILOCK_EXCL);
}
/* Handle various SYNC-type writes */
#if 0
// if ((file->f_flags & O_SYNC) || IS_SYNC(inode)) {
#endif
if (ioflag & IO_SYNC) {
/*
* If we're treating this as O_DSYNC and we have not updated the
* size, force the log.
*/
if (!(mp->m_flags & XFS_MOUNT_OSYNCISOSYNC) &&
!(xip->i_update_size)) {
xfs_inode_log_item_t *iip = xip->i_itemp;
/*
* If an allocation transaction occurred
* without extending the size, then we have to force
* the log up the proper point to ensure that the
* allocation is permanent. We can't count on
* the fact that buffered writes lock out direct I/O
* writes - the direct I/O write could have extended
* the size nontransactionally, then finished before
* we started. xfs_write_file will think that the file
* didn't grow but the update isn't safe unless the
* size change is logged.
*
* Force the log if we've committed a transaction
* against the inode or if someone else has and
* the commit record hasn't gone to disk (e.g.
* the inode is pinned). This guarantees that
* all changes affecting the inode are permanent
* when we return.
*/
if (iip && iip->ili_last_lsn) {
xfs_log_force(mp, iip->ili_last_lsn,
XFS_LOG_FORCE | XFS_LOG_SYNC);
} else if (xfs_ipincount(xip) > 0) {
xfs_log_force(mp, (xfs_lsn_t)0,
XFS_LOG_FORCE | XFS_LOG_SYNC);
}
} else {
xfs_trans_t *tp;
/*
* O_SYNC or O_DSYNC _with_ a size update are handled
* the same way.
*
* If the write was synchronous then we need to make
* sure that the inode modification time is permanent.
* We'll have updated the timestamp above, so here
* we use a synchronous transaction to log the inode.
* It's not fast, but it's necessary.
*
* If this a dsync write and the size got changed
* non-transactionally, then we need to ensure that
* the size change gets logged in a synchronous
* transaction.
*/
tp = xfs_trans_alloc(mp, XFS_TRANS_WRITE_SYNC);
if ((error = xfs_trans_reserve(tp, 0,
XFS_SWRITE_LOG_RES(mp),
0, 0, 0))) {
/* Transaction reserve failed */
xfs_trans_cancel(tp, 0);
} else {
/* Transaction reserve successful */
xfs_ilock(xip, XFS_ILOCK_EXCL);
xfs_trans_ijoin(tp, xip, XFS_ILOCK_EXCL);
xfs_trans_ihold(tp, xip);
xfs_trans_log_inode(tp, xip, XFS_ILOG_CORE);
xfs_trans_set_sync(tp);
error = xfs_trans_commit(tp, 0, NULL);
xfs_iunlock(xip, XFS_ILOCK_EXCL);
}
if (error)
goto out_unlock_internal;
}
xfs_rwunlock(bdp, locktype);
return ret;
} /* (ioflags & O_SYNC) */
out_unlock_internal:
xfs_rwunlock(bdp, locktype);
#if 0
out_unlock_mutex:
if (need_i_mutex)
mutex_unlock(&inode->i_mutex);
#endif
//out_nounlocks:
return -error;
}
/*
* Initiate IO on given buffer.
*/
int
xfs_buf_iorequest(struct xfs_buf *bp)
{
bp->b_flags &= ~(B_INVAL|B_DONE);
bp->b_ioflags &= ~BIO_ERROR;
if (bp->b_flags & B_ASYNC)
BUF_KERNPROC(bp);
if (bp->b_vp == NULL) {
if (bp->b_iocmd == BIO_WRITE) {
bp->b_flags &= ~(B_DELWRI | B_DEFERRED);
bufobj_wref(bp->b_bufobj);
}
bp->b_iooffset = (bp->b_blkno << BBSHIFT);
bstrategy(bp);
} else {
if (bp->b_iocmd == BIO_WRITE) {
/* Mark the buffer clean */
bundirty(bp);
bufobj_wref(bp->b_bufobj);
vfs_busy_pages(bp, 1);
} else if (bp->b_iocmd == BIO_READ) {
vfs_busy_pages(bp, 0);
}
bp->b_iooffset = dbtob(bp->b_blkno);
bstrategy(bp);
}
return 0;
}
/*
* All xfs metadata buffers except log state machine buffers
* get this attached as their b_bdstrat callback function.
* This is so that we can catch a buffer
* after prematurely unpinning it to forcibly shutdown the filesystem.
*/
int
xfs_bdstrat_cb(struct xfs_buf *bp)
{
xfs_mount_t *mp;
mp = XFS_BUF_FSPRIVATE3(bp, xfs_mount_t *);
if (!XFS_FORCED_SHUTDOWN(mp)) {
xfs_buf_iorequest(bp);
return 0;
} else {
xfs_buftrace("XFS__BDSTRAT IOERROR", bp);
/*
* Metadata write that didn't get logged but
* written delayed anyway. These aren't associated
* with a transaction, and can be ignored.
*/
if (XFS_BUF_IODONE_FUNC(bp) == NULL &&
(XFS_BUF_ISREAD(bp)) == 0)
return (xfs_bioerror_relse(bp));
else
return (xfs_bioerror(bp));
}
}
int
xfs_bmap(bhv_desc_t *bdp,
xfs_off_t offset,
ssize_t count,
int flags,
xfs_iomap_t *iomapp,
int *niomaps)
{
xfs_inode_t *ip = XFS_BHVTOI(bdp);
xfs_iocore_t *io = &ip->i_iocore;
ASSERT((ip->i_d.di_mode & S_IFMT) == S_IFREG);
ASSERT(((ip->i_d.di_flags & XFS_DIFLAG_REALTIME) != 0) ==
((ip->i_iocore.io_flags & XFS_IOCORE_RT) != 0));
return xfs_iomap(io, offset, count, flags, iomapp, niomaps);
}
/*
* Wrapper around bdstrat so that we can stop data
* from going to disk in case we are shutting down the filesystem.
* Typically user data goes thru this path; one of the exceptions
* is the superblock.
*/
int
xfsbdstrat(
struct xfs_mount *mp,
struct xfs_buf *bp)
{
ASSERT(mp);
if (!XFS_FORCED_SHUTDOWN(mp)) {
xfs_buf_iorequest(bp);
return 0;
}
xfs_buftrace("XFSBDSTRAT IOERROR", bp);
return (xfs_bioerror_relse(bp));
}
/*
* If the underlying (data/log/rt) device is readonly, there are some
* operations that cannot proceed.
*/
int
xfs_dev_is_read_only(
xfs_mount_t *mp,
char *message)
{
if (xfs_readonly_buftarg(mp->m_ddev_targp) ||
xfs_readonly_buftarg(mp->m_logdev_targp) ||
(mp->m_rtdev_targp && xfs_readonly_buftarg(mp->m_rtdev_targp))) {
cmn_err(CE_NOTE,
"XFS: %s required on read-only device.", message);
cmn_err(CE_NOTE,
"XFS: write access unavailable, cannot proceed.");
return EROFS;
}
return 0;
}

View File

@ -1,106 +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_FRW_H__
#define __XFS_FRW_H__
struct xfs_vnode;
struct bhv_desc;
struct xfs_mount;
struct xfs_iocore;
struct xfs_inode;
struct xfs_bmbt_irec;
struct xfs_buf;
struct xfs_iomap;
#if defined(XFS_RW_TRACE)
/*
* Defines for the trace mechanisms in xfs_lrw.c.
*/
#define XFS_RW_KTRACE_SIZE 128
#define XFS_READ_ENTER 1
#define XFS_WRITE_ENTER 2
#define XFS_IOMAP_READ_ENTER 3
#define XFS_IOMAP_WRITE_ENTER 4
#define XFS_IOMAP_READ_MAP 5
#define XFS_IOMAP_WRITE_MAP 6
#define XFS_IOMAP_WRITE_NOSPACE 7
#define XFS_ITRUNC_START 8
#define XFS_ITRUNC_FINISH1 9
#define XFS_ITRUNC_FINISH2 10
#define XFS_CTRUNC1 11
#define XFS_CTRUNC2 12
#define XFS_CTRUNC3 13
#define XFS_CTRUNC4 14
#define XFS_CTRUNC5 15
#define XFS_CTRUNC6 16
#define XFS_BUNMAPI 17
#define XFS_INVAL_CACHED 18
#define XFS_DIORD_ENTER 19
#define XFS_DIOWR_ENTER 20
#define XFS_SENDFILE_ENTER 21
#define XFS_WRITEPAGE_ENTER 22
#define XFS_RELEASEPAGE_ENTER 23
#define XFS_IOMAP_ALLOC_ENTER 24
#define XFS_IOMAP_ALLOC_MAP 25
#define XFS_IOMAP_UNWRITTEN 26
extern void xfs_rw_enter_trace(int, struct xfs_iocore *,
const char *, size_t, loff_t, int);
extern void xfs_inval_cached_trace(struct xfs_iocore *,
xfs_off_t, xfs_off_t, xfs_off_t, xfs_off_t);
#else
#define xfs_rw_enter_trace(tag, io, buf, size, offset, ioflags)
#define xfs_inval_cached_trace(io, offset, len, first, last)
#endif
/*
* Maximum count of bmaps used by read and write paths.
*/
#define XFS_MAX_RW_NBMAPS 4
extern int xfs_bmap(struct bhv_desc *, xfs_off_t, ssize_t, int,
struct xfs_iomap *, int *);
extern int xfsbdstrat(struct xfs_mount *, struct xfs_buf *);
extern int xfs_bdstrat_cb(struct xfs_buf *);
extern int xfs_zero_eof(struct xfs_vnode *, struct xfs_iocore *, xfs_off_t,
xfs_fsize_t, xfs_fsize_t);
extern void xfs_inval_cached_pages(struct xfs_vnode*, struct xfs_iocore *,
xfs_off_t, int, int);
extern ssize_t xfs_read(bhv_desc_t *, uio_t *, int, cred_t *);
extern ssize_t xfs_write(bhv_desc_t *, uio_t *, int, cred_t *);
extern int xfs_dev_is_read_only(struct xfs_mount *, char *);
extern int xfs_read_file(struct xfs_mount *mp, struct xfs_inode *ip, struct uio *uio,
int ioflag);
extern int xfs_write_file(struct xfs_inode *, struct uio *, int);
#endif /* __XFS_FRW_H__ */

View File

@ -1,131 +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/
*/
#include "xfs.h"
/*
* Stub for no-op vnode operations that return error status.
*/
int
fs_noerr()
{
return 0;
}
/*
* Operation unsupported under this file system.
*/
int
fs_nosys()
{
return ENOSYS;
}
/*
* Stub for inactive, strategy, and read/write lock/unlock. Does nothing.
*/
/* ARGSUSED */
void
fs_noval()
{
}
/*
* vnode pcache layer for vnode_tosspages.
* 'last' parameter unused but left in for IRIX compatibility
*/
void
fs_tosspages(
bhv_desc_t *bdp,
xfs_off_t first,
xfs_off_t last,
int fiopt)
{
#ifdef XXXKAN
vnode_t *vp = BHV_TO_VNODE(bdp);
struct inode *ip = LINVFS_GET_IP(vp);
if (VN_CACHED(vp))
truncate_inode_pages(ip->i_mapping, first);
#endif
}
/*
* vnode pcache layer for vnode_flushinval_pages.
* 'last' parameter unused but left in for IRIX compatibility
*/
void
fs_flushinval_pages(
bhv_desc_t *bdp,
xfs_off_t first,
xfs_off_t last,
int fiopt)
{
#ifdef XXXKAN
vnode_t *vp = BHV_TO_VNODE(bdp);
struct inode *ip = LINVFS_GET_IP(vp);
if (VN_CACHED(vp)) {
filemap_fdatasync(ip->i_mapping);
fsync_inode_data_buffers(ip);
filemap_fdatawait(ip->i_mapping);
truncate_inode_pages(ip->i_mapping, first);
}
#endif
}
/*
* vnode pcache layer for vnode_flush_pages.
* 'last' parameter unused but left in for IRIX compatibility
*/
int
fs_flush_pages(
bhv_desc_t *bdp,
xfs_off_t first,
xfs_off_t last,
uint64_t flags,
int fiopt)
{
#ifdef XXXKAN
vnode_t *vp = BHV_TO_VNODE(bdp);
struct inode *ip = LINVFS_GET_IP(vp);
if (VN_CACHED(vp)) {
filemap_fdatasync(ip->i_mapping);
fsync_inode_data_buffers(ip);
filemap_fdatawait(ip->i_mapping);
}
#endif
return 0;
}

View File

@ -1,49 +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_SUBR_H__
#define __XFS_SUBR_H__
/*
* Utilities shared among file system implementations.
*/
struct cred;
extern int fs_noerr(void);
extern int fs_nosys(void);
extern int fs_nodev(void);
extern void fs_noval(void);
extern void fs_tosspages(bhv_desc_t *, xfs_off_t, xfs_off_t, int);
extern void fs_flushinval_pages(bhv_desc_t *, xfs_off_t, xfs_off_t, int);
extern int fs_flush_pages(bhv_desc_t *, xfs_off_t, xfs_off_t, uint64_t, int);
#endif /* __XFS_FS_SUBR_H__ */

View File

@ -1,77 +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/
*/
/*
* This file contains globals needed by XFS that were normally defined
* somewhere else in IRIX.
*/
#include "xfs.h"
#include "xfs_types.h"
#include "xfs_bmap_btree.h"
#include "xfs_bit.h"
#include "xfs_refcache.h"
/*
* Tunable XFS parameters. xfs_params is required even when CONFIG_SYSCTL=n,
* other XFS code uses these values.
*/
xfs_param_t xfs_params = {
/* MIN DFLT MAX */
#ifdef HAVE_REFCACHE
.refcache_size = { 0, 128, XFS_REFCACHE_SIZE_MAX },
.refcache_purge = { 0, 32, XFS_REFCACHE_SIZE_MAX },
#endif
.restrict_chown = { 0, 1, 1 },
.sgid_inherit = { 0, 0, 1 },
.symlink_mode = { 0, 0, 1 },
.panic_mask = { 0, 0, 127 },
.error_level = { 0, 3, 11 },
.syncd_timer = { 1*100, 30*100, 7200*100},
.probe_dmapi = { 0, 0, 1 },
.probe_ioops = { 0, 0, 1 },
.probe_quota = { 0, 1, 1 },
.stats_clear = { 0, 0, 1 },
.inherit_sync = { 0, 1, 1 },
.inherit_nodump = { 0, 1, 1 },
.inherit_noatim = { 0, 1, 1 },
.xfs_buf_timer = { 100/2, 1*100, 30*100 },
.xfs_buf_age = { 1*100, 15*100, 7200*100},
.inherit_nosym = { 0, 0, 1 },
.rotorstep = { 1, 1, 255 },
};
/*
* Global system credential structure.
*/
cred_t sys_cred_val, *sys_cred = &sys_cred_val;

File diff suppressed because it is too large Load Diff

View File

@ -1,61 +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_IOPS_H__
#define __XFS_IOPS_H__
/*
* Extended system attributes.
* So far only POSIX ACLs are supported, but this will need to
* grow in time (capabilities, mandatory access control, etc).
*/
#define XFS_SYSTEM_NAMESPACE SYSTEM_POSIXACL
/*
* Define a table of the namespaces XFS supports
*/
typedef int (*xattr_exists_t)(xfs_vnode_t *);
typedef struct xattr_namespace {
char *name;
unsigned int namelen;
xattr_exists_t exists;
} xattr_namespace_t;
#define SYSTEM_NAMES 0
#define ROOT_NAMES 1
#define USER_NAMES 2
extern struct xattr_namespace *xfs_namespaces;
extern int xfs_ioctl(struct bhv_desc *, struct inode *, struct file *,
int, u_long, void *);
#endif /* __XFS_IOPS_H__ */

View File

@ -1,500 +0,0 @@
/*
* Copyright (c) 2001,2006 Alexander Kabaev, Russell Cattelan Digital Elves Inc.
* 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/malloc.h>
#include <sys/vnode.h>
#include <sys/mount.h>
#include <sys/namei.h>
#include <geom/geom.h>
#include <geom/geom_vfs.h>
#include "xfs.h"
#include "xfs_types.h"
#include "xfs_bit.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_alloc_btree.h"
#include "xfs_bmap_btree.h"
#include "xfs_ialloc_btree.h"
#include "xfs_btree.h"
#include "xfs_attr_sf.h"
#include "xfs_dir_sf.h"
#include "xfs_dir2_sf.h"
#include "xfs_dinode.h"
#include "xfs_ialloc.h"
#include "xfs_inode.h"
#include "xfs_alloc.h"
#include "xfs_rtalloc.h"
#include "xfs_bmap.h"
#include "xfs_error.h"
#include "xfs_rw.h"
#include "xfs_quota.h"
#include "xfs_fsops.h"
#include "xfs_clnt.h"
#include <xfs_mountops.h>
static MALLOC_DEFINE(M_XFSNODE, "XFS node", "XFS vnode private part");
static vfs_mount_t _xfs_mount;
static vfs_unmount_t _xfs_unmount;
static vfs_root_t _xfs_root;
static vfs_quotactl_t _xfs_quotactl;
static vfs_statfs_t _xfs_statfs;
static vfs_sync_t _xfs_sync;
static vfs_vget_t _xfs_vget;
static vfs_fhtovp_t _xfs_fhtovp;
static vfs_init_t _xfs_init;
static vfs_uninit_t _xfs_uninit;
static vfs_extattrctl_t _xfs_extattrctl;
static b_strategy_t xfs_geom_strategy;
static const char *xfs_opts[] =
{ "from", "flags", "logbufs", "logbufsize",
"rtname", "logname", "iosizelog", "sunit",
"swidth", "export",
NULL };
static void
parse_int(struct mount *mp, const char *opt, int *val, int *error)
{
char *tmp, *ep;
tmp = vfs_getopts(mp->mnt_optnew, opt, error);
if (*error != 0) {
return;
}
if (tmp != NULL) {
*val = (int)strtol(tmp, &ep, 10);
if (*ep) {
*error = EINVAL;
return;
}
}
}
static int
_xfs_param_copyin(struct mount *mp, struct thread *td)
{
struct xfsmount *xmp = MNTTOXFS(mp);
struct xfs_mount_args *args = &xmp->m_args;
char *path;
char *fsname;
char *rtname;
char *logname;
int error;
path = vfs_getopts(mp->mnt_optnew, "fspath", &error);
if (error)
return (error);
bzero(args, sizeof(struct xfs_mount_args));
args->logbufs = -1;
args->logbufsize = -1;
parse_int(mp, "flags", &args->flags, &error);
if (error != 0 && error != ENOENT)
return error;
args->flags |= XFSMNT_32BITINODES;
parse_int(mp, "sunit", &args->sunit, &error);
if (error != 0 && error != ENOENT)
return error;
parse_int(mp, "swidth", &args->swidth, &error);
if (error != 0 && error != ENOENT)
return error;
parse_int(mp, "logbufs", &args->logbufs, &error);
if (error != 0 && error != ENOENT)
return error;
parse_int(mp, "logbufsize", &args->logbufsize, &error);
if (error != 0 && error != ENOENT)
return error;
fsname = vfs_getopts(mp->mnt_optnew, "from", &error);
if (error == 0 && fsname != NULL) {
strncpy(args->fsname, fsname, sizeof(args->fsname) - 1);
}
logname = vfs_getopts(mp->mnt_optnew, "logname", &error);
if (error == 0 && logname != NULL) {
strncpy(args->logname, logname, sizeof(args->logname) - 1);
}
rtname = vfs_getopts(mp->mnt_optnew, "rtname", &error);
if (error == 0 && rtname != NULL) {
strncpy(args->rtname, rtname, sizeof(args->rtname) - 1);
}
strncpy(args->mtpt, path, sizeof(args->mtpt));
printf("fsname '%s' logname '%s' rtname '%s'\n"
"flags 0x%x sunit %d swidth %d logbufs %d logbufsize %d\n",
args->fsname, args->logname, args->rtname, args->flags,
args->sunit, args->swidth, args->logbufs, args->logbufsize);
vfs_mountedfrom(mp, args->fsname);
return (0);
}
static int
_xfs_mount(struct mount *mp)
{
struct xfsmount *xmp;
struct xfs_vnode *rootvp;
struct ucred *curcred;
struct vnode *rvp, *devvp;
struct cdev *ddev;
struct g_consumer *cp;
struct thread *td;
int error;
td = curthread;
ddev = NULL;
cp = NULL;
if (vfs_filteropt(mp->mnt_optnew, xfs_opts))
return (EINVAL);
if (mp->mnt_flag & MNT_UPDATE)
return (0);
if ((mp->mnt_flag & MNT_RDONLY) == 0)
return (EPERM);
xmp = xfsmount_allocate(mp);
if (xmp == NULL)
return (ENOMEM);
if((error = _xfs_param_copyin(mp, td)) != 0)
goto fail;
curcred = td->td_ucred;
XVFS_MOUNT(XFSTOVFS(xmp), &xmp->m_args, curcred, error);
if (error)
goto fail;
XVFS_ROOT(XFSTOVFS(xmp), &rootvp, error);
ddev = XFS_VFSTOM(XFSTOVFS(xmp))->m_ddev_targp->dev;
devvp = XFS_VFSTOM(XFSTOVFS(xmp))->m_ddev_targp->specvp;
if (error)
goto fail_unmount;
if (ddev->si_iosize_max != 0)
mp->mnt_iosize_max = ddev->si_iosize_max;
if (mp->mnt_iosize_max > MAXPHYS)
mp->mnt_iosize_max = MAXPHYS;
mp->mnt_flag |= MNT_LOCAL;
mp->mnt_stat.f_fsid.val[0] = dev2udev(ddev);
mp->mnt_stat.f_fsid.val[1] = mp->mnt_vfc->vfc_typenum;
if ((error = VFS_STATFS(mp, &mp->mnt_stat)) != 0)
goto fail_unmount;
rvp = rootvp->v_vnode;
rvp->v_vflag |= VV_ROOT;
VN_RELE(rootvp);
return (0);
fail_unmount:
XVFS_UNMOUNT(XFSTOVFS(xmp), 0, curcred, error);
if (devvp != NULL) {
cp = devvp->v_bufobj.bo_private;
if (cp != NULL) {
DROP_GIANT();
g_topology_lock();
g_vfs_close(cp);
g_topology_unlock();
PICKUP_GIANT();
}
}
fail:
if (xmp != NULL)
xfsmount_deallocate(xmp);
return (error);
}
/*
* Free reference to null layer
*/
static int
_xfs_unmount(mp, mntflags)
struct mount *mp;
int mntflags;
{
struct vnode *devvp;
struct g_consumer *cp;
int error;
cp = NULL;
devvp = NULL;
devvp = XFS_VFSTOM((MNTTOVFS(mp)))->m_ddev_targp->specvp;
if (devvp != NULL)
cp = devvp->v_bufobj.bo_private;
XVFS_UNMOUNT(MNTTOVFS(mp), 0, curthread->td_ucred, error);
if (error == 0) {
if (cp != NULL) {
DROP_GIANT();
g_topology_lock();
g_vfs_close(cp);
g_topology_unlock();
PICKUP_GIANT();
}
}
return (error);
}
static int
_xfs_root(mp, flags, vpp)
struct mount *mp;
int flags;
struct vnode **vpp;
{
xfs_vnode_t *vp;
int error;
XVFS_ROOT(MNTTOVFS(mp), &vp, error);
if (error == 0) {
*vpp = vp->v_vnode;
VOP_LOCK(*vpp, flags);
}
return (error);
}
static int
_xfs_quotactl(mp, cmd, uid, arg)
struct mount *mp;
int cmd;
uid_t uid;
void *arg;
{
printf("xfs_quotactl\n");
return EOPNOTSUPP;
}
static int
_xfs_statfs(mp, sbp)
struct mount *mp;
struct statfs *sbp;
{
int error;
XVFS_STATVFS(MNTTOVFS(mp), sbp, NULL, error);
if (error)
return error;
/* Fix up the values XFS statvfs calls does not know about. */
sbp->f_iosize = sbp->f_bsize;
return (error);
}
static int
_xfs_sync(mp, waitfor)
struct mount *mp;
int waitfor;
{
int error;
int flags = SYNC_FSDATA|SYNC_ATTR|SYNC_REFCACHE;
if (waitfor == MNT_WAIT)
flags |= SYNC_WAIT;
else if (waitfor == MNT_LAZY)
flags |= SYNC_BDFLUSH;
XVFS_SYNC(MNTTOVFS(mp), flags, curthread->td_ucred, error);
return (error);
}
static int
_xfs_vget(mp, ino, flags, vpp)
struct mount *mp;
ino_t ino;
int flags;
struct vnode **vpp;
{
xfs_vnode_t *vp = NULL;
int error;
printf("XVFS_GET_VNODE(MNTTOVFS(mp), &vp, ino, error);\n");
error = ENOSYS;
if (error == 0)
*vpp = vp->v_vnode;
return (error);
}
static int
_xfs_fhtovp(mp, fidp, flags, vpp)
struct mount *mp;
struct fid *fidp;
int flags;
struct vnode **vpp;
{
printf("xfs_fhtovp\n");
return ENOSYS;
}
static int
_xfs_extattrctl(struct mount *mp, int cm,
struct vnode *filename_v,
int attrnamespace, const char *attrname)
{
printf("xfs_extattrctl\n");
return ENOSYS;
}
int
_xfs_init(vfsp)
struct vfsconf *vfsp;
{
int error;
error = init_xfs_fs();
return (error);
}
int
_xfs_uninit(vfsp)
struct vfsconf *vfsp;
{
exit_xfs_fs();
return 0;
}
static struct vfsops xfs_fsops = {
.vfs_mount = _xfs_mount,
.vfs_unmount = _xfs_unmount,
.vfs_root = _xfs_root,
.vfs_quotactl = _xfs_quotactl,
.vfs_statfs = _xfs_statfs,
.vfs_sync = _xfs_sync,
.vfs_vget = _xfs_vget,
.vfs_fhtovp = _xfs_fhtovp,
.vfs_init = _xfs_init,
.vfs_uninit = _xfs_uninit,
.vfs_extattrctl = _xfs_extattrctl,
};
VFS_SET(xfs_fsops, xfs, VFCF_READONLY);
/*
* Copy GEOM VFS functions here to provide a conveniet place to
* track all XFS-related IO without being distracted by other
* filesystems which happen to be mounted on the machine at the
* same time.
*/
static void
xfs_geom_biodone(struct bio *bip)
{
struct buf *bp;
if (bip->bio_error) {
printf("g_vfs_done():");
g_print_bio(bip);
printf("error = %d\n", bip->bio_error);
}
bp = bip->bio_caller2;
bp->b_error = bip->bio_error;
bp->b_ioflags = bip->bio_flags;
if (bip->bio_error)
bp->b_ioflags |= BIO_ERROR;
bp->b_resid = bp->b_bcount - bip->bio_completed;
g_destroy_bio(bip);
mtx_lock(&Giant);
bufdone(bp);
mtx_unlock(&Giant);
}
static void
xfs_geom_strategy(struct bufobj *bo, struct buf *bp)
{
struct g_consumer *cp;
struct bio *bip;
cp = bo->bo_private;
G_VALID_CONSUMER(cp);
bip = g_alloc_bio();
bip->bio_cmd = bp->b_iocmd;
bip->bio_offset = bp->b_iooffset;
bip->bio_data = bp->b_data;
bip->bio_done = xfs_geom_biodone;
bip->bio_caller2 = bp;
bip->bio_length = bp->b_bcount;
g_io_request(bip, cp);
}
static int
xfs_geom_bufwrite(struct buf *bp)
{
return bufwrite(bp);
}
static int
xfs_geom_bufsync(struct bufobj *bo, int waitfor)
{
return (bufsync(bo, waitfor));
}
static void
xfs_geom_bufbdflush(struct bufobj *bo, struct buf *bp)
{
bufbdflush(bo, bp);
}
struct buf_ops xfs_bo_ops = {
.bop_name = "XFS",
.bop_write = xfs_geom_bufwrite,
.bop_strategy = xfs_geom_strategy,
.bop_sync = xfs_geom_bufsync,
.bop_bdflush = xfs_geom_bufbdflush,
};

View File

@ -1,59 +0,0 @@
/*-
* Copyright (c) 2001 Alexander Kabaev
* 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 _XFS_XFS_H_
#define _XFS_XFS_H_
#define XFSFS_VMAJOR 0
#define XFS_VMINOR 1
#define XFS_VERSION ((XFS_VMAJOR << 16) | XFS_VMINOR)
#define XFS_NAME "xfs"
#ifdef _KERNEL
struct xfsmount {
struct xfs_mount_args m_args; /* Mount parameters */
struct mount * m_mp; /* Back pointer */
xfs_vfs_t m_vfs; /* SHOULD BE FIRST */
};
#define XFSTOMNT(xmp) ((xmp)->m_mp)
#define XFSTOVFS(xmp) (&(xmp)->m_vfs)
#define MNTTOXFS(mp) ((struct xfsmount *)((mp)->mnt_data))
#define MNTTOVFS(mp) XFSTOVFS(MNTTOXFS(mp))
#define VFSTOMNT(vfsp) (vfsp)->vfs_mp
#define VFSTOXFS(vfsp) MNTTOXFS(VFSTOMNT(vfsp))
struct xfsmount *xfsmount_allocate(struct mount *mp);
void xfsmount_deallocate(struct xfsmount *xmp);
#endif /* _KERNEL */
#endif /* _XFS_XFS_H*/

View File

@ -1,16 +0,0 @@
#ifndef __XFS_NODE_H__
#define __XFS_NODE_H__
/*
* Save one allocation on FreeBSD and always allocate both inode and
* xfs_vnode struct as a single memory block.
*/
struct xfs_node
{
struct xfs_inode n_inode;
struct xfs_vnode n_vnode;
};
#define XFS_CAST_IP2VP(ip) (&((struct xfs_node *)(ip))->n_vnode)
#endif /* __XFS_NODE_H__ */

View File

@ -1,105 +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.h"
struct xfsstats xfsstats;
STATIC int
xfs_read_xfsstats(
char *buffer,
char **start,
off_t offset,
int count,
int *eof,
void *data)
{
int i, j, len;
static struct xstats_entry {
char *desc;
int endpoint;
} xstats[] = {
{ "extent_alloc", XFSSTAT_END_EXTENT_ALLOC },
{ "abt", XFSSTAT_END_ALLOC_BTREE },
{ "blk_map", XFSSTAT_END_BLOCK_MAPPING },
{ "bmbt", XFSSTAT_END_BLOCK_MAP_BTREE },
{ "dir", XFSSTAT_END_DIRECTORY_OPS },
{ "trans", XFSSTAT_END_TRANSACTIONS },
{ "ig", XFSSTAT_END_INODE_OPS },
{ "log", XFSSTAT_END_LOG_OPS },
{ "push_ail", XFSSTAT_END_TAIL_PUSHING },
{ "xstrat", XFSSTAT_END_WRITE_CONVERT },
{ "rw", XFSSTAT_END_READ_WRITE_OPS },
{ "attr", XFSSTAT_END_ATTRIBUTE_OPS },
{ "icluster", XFSSTAT_END_INODE_CLUSTER },
{ "vnodes", XFSSTAT_END_VNODE_OPS },
};
for (i=j=len = 0; i < sizeof(xstats)/sizeof(struct xstats_entry); i++) {
len += sprintf(buffer + len, "%s", xstats[i].desc);
/* inner loop does each group */
while (j < xstats[i].endpoint) {
len += sprintf(buffer + len, " %u",
*(((__u32*)&xfsstats) + j));
j++;
}
buffer[len++] = '\n';
}
/* extra precision counters */
len += sprintf(buffer + len, "xpc %ju %ju %ju\n",
(uintmax_t)xfsstats.xs_xstrat_bytes,
(uintmax_t)xfsstats.xs_write_bytes,
(uintmax_t)xfsstats.xs_read_bytes);
if (offset >= len) {
*start = buffer;
*eof = 1;
return 0;
}
*start = buffer + offset;
if ((len -= offset) > count)
return count;
*eof = 1;
return len;
}
void
xfs_init_procfs(void)
{
if (&xfs_read_xfsstats != NULL);
}
void
xfs_cleanup_procfs(void)
{
}

View File

@ -1,161 +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_STATS_H__
#define __XFS_STATS_H__
#if !defined(XFS_STATS_OFF)
/*
* XFS global statistics
*/
struct xfsstats {
# define XFSSTAT_END_EXTENT_ALLOC 4
__uint32_t xs_allocx;
__uint32_t xs_allocb;
__uint32_t xs_freex;
__uint32_t xs_freeb;
# define XFSSTAT_END_ALLOC_BTREE (XFSSTAT_END_EXTENT_ALLOC+4)
__uint32_t xs_abt_lookup;
__uint32_t xs_abt_compare;
__uint32_t xs_abt_insrec;
__uint32_t xs_abt_delrec;
# define XFSSTAT_END_BLOCK_MAPPING (XFSSTAT_END_ALLOC_BTREE+7)
__uint32_t xs_blk_mapr;
__uint32_t xs_blk_mapw;
__uint32_t xs_blk_unmap;
__uint32_t xs_add_exlist;
__uint32_t xs_del_exlist;
__uint32_t xs_look_exlist;
__uint32_t xs_cmp_exlist;
# define XFSSTAT_END_BLOCK_MAP_BTREE (XFSSTAT_END_BLOCK_MAPPING+4)
__uint32_t xs_bmbt_lookup;
__uint32_t xs_bmbt_compare;
__uint32_t xs_bmbt_insrec;
__uint32_t xs_bmbt_delrec;
# define XFSSTAT_END_DIRECTORY_OPS (XFSSTAT_END_BLOCK_MAP_BTREE+4)
__uint32_t xs_dir_lookup;
__uint32_t xs_dir_create;
__uint32_t xs_dir_remove;
__uint32_t xs_dir_getdents;
# define XFSSTAT_END_TRANSACTIONS (XFSSTAT_END_DIRECTORY_OPS+3)
__uint32_t xs_trans_sync;
__uint32_t xs_trans_async;
__uint32_t xs_trans_empty;
# define XFSSTAT_END_INODE_OPS (XFSSTAT_END_TRANSACTIONS+7)
__uint32_t xs_ig_attempts;
__uint32_t xs_ig_found;
__uint32_t xs_ig_frecycle;
__uint32_t xs_ig_missed;
__uint32_t xs_ig_dup;
__uint32_t xs_ig_reclaims;
__uint32_t xs_ig_attrchg;
# define XFSSTAT_END_LOG_OPS (XFSSTAT_END_INODE_OPS+5)
__uint32_t xs_log_writes;
__uint32_t xs_log_blocks;
__uint32_t xs_log_noiclogs;
__uint32_t xs_log_force;
__uint32_t xs_log_force_sleep;
# define XFSSTAT_END_TAIL_PUSHING (XFSSTAT_END_LOG_OPS+10)
__uint32_t xs_try_logspace;
__uint32_t xs_sleep_logspace;
__uint32_t xs_push_ail;
__uint32_t xs_push_ail_success;
__uint32_t xs_push_ail_pushbuf;
__uint32_t xs_push_ail_pinned;
__uint32_t xs_push_ail_locked;
__uint32_t xs_push_ail_flushing;
__uint32_t xs_push_ail_restarts;
__uint32_t xs_push_ail_flush;
# define XFSSTAT_END_WRITE_CONVERT (XFSSTAT_END_TAIL_PUSHING+2)
__uint32_t xs_xstrat_quick;
__uint32_t xs_xstrat_split;
# define XFSSTAT_END_READ_WRITE_OPS (XFSSTAT_END_WRITE_CONVERT+2)
__uint32_t xs_write_calls;
__uint32_t xs_read_calls;
# define XFSSTAT_END_ATTRIBUTE_OPS (XFSSTAT_END_READ_WRITE_OPS+4)
__uint32_t xs_attr_get;
__uint32_t xs_attr_set;
__uint32_t xs_attr_remove;
__uint32_t xs_attr_list;
# define XFSSTAT_END_INODE_CLUSTER (XFSSTAT_END_ATTRIBUTE_OPS+3)
__uint32_t xs_iflush_count;
__uint32_t xs_icluster_flushcnt;
__uint32_t xs_icluster_flushinode;
# define XFSSTAT_END_VNODE_OPS (XFSSTAT_END_INODE_CLUSTER+8)
__uint32_t vn_active; /* # vnodes not on free lists */
__uint32_t vn_alloc; /* # times vn_alloc called */
__uint32_t vn_get; /* # times vn_get called */
__uint32_t vn_hold; /* # times vn_hold called */
__uint32_t vn_rele; /* # times vn_rele called */
__uint32_t vn_reclaim; /* # times vn_reclaim called */
__uint32_t vn_remove; /* # times vn_remove called */
__uint32_t vn_free; /* # times vn_free called */
#define XFSSTAT_END_BUF (XFSSTAT_END_VNODE_OPS+9)
__uint32_t pb_get;
__uint32_t pb_create;
__uint32_t pb_get_locked;
__uint32_t pb_get_locked_waited;
__uint32_t pb_busy_locked;
__uint32_t pb_miss_locked;
__uint32_t pb_page_retries;
__uint32_t pb_page_found;
__uint32_t pb_get_read;
/* Extra precision counters */
__uint64_t xs_xstrat_bytes;
__uint64_t xs_write_bytes;
__uint64_t xs_read_bytes;
};
extern struct xfsstats xfsstats;
# define XFS_STATS_INC(count) ( xfsstats.count++ )
# define XFS_STATS_DEC(count) ( xfsstats.count-- )
# define XFS_STATS_ADD(count, inc) ( xfsstats.count += (inc) )
extern void xfs_init_procfs(void);
extern void xfs_cleanup_procfs(void);
#else /* !CONFIG_PROC_FS */
# define XFS_STATS_INC(count)
# define XFS_STATS_DEC(count)
# define XFS_STATS_ADD(count, inc)
static __inline void xfs_init_procfs(void) { };
static __inline void xfs_cleanup_procfs(void) { };
#endif /* !CONFIG_PROC_FS */
#endif /* __XFS_STATS_H__ */

View File

@ -1,279 +0,0 @@
/*
* Copyright (c) 2000-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"
#include "xfs_bit.h"
#include "xfs_log.h"
#include "xfs_clnt.h"
#include "xfs_inum.h"
#include "xfs_trans.h"
#include "xfs_sb.h"
#include "xfs_ag.h"
#include "xfs_dir.h"
#include "xfs_dir2.h"
#include "xfs_alloc.h"
#include "xfs_dmapi.h"
#include "xfs_quota.h"
#include "xfs_mount.h"
#include "xfs_bmap_btree.h"
#include "xfs_alloc_btree.h"
#include "xfs_ialloc_btree.h"
#include "xfs_dir_sf.h"
#include "xfs_dir2_sf.h"
#include "xfs_attr_sf.h"
#include "xfs_dinode.h"
#include "xfs_inode.h"
#include "xfs_btree.h"
#include "xfs_ialloc.h"
#include "xfs_bmap.h"
#include "xfs_rtalloc.h"
#include "xfs_error.h"
#include "xfs_itable.h"
#include "xfs_rw.h"
#include "xfs_acl.h"
#include "xfs_cap.h"
#include "xfs_mac.h"
#include "xfs_attr.h"
#include "xfs_buf_item.h"
#include "xfs_utils.h"
#include "xfs_version.h"
#include "xfs_buf.h"
#include <sys/priv.h>
#include <geom/geom.h>
#include <geom/geom_vfs.h>
extern struct vop_vector xfs_fifoops;
extern struct xfs_vnodeops xfs_vnodeops;
__uint64_t
xfs_max_file_offset(
unsigned int blockshift)
{
return (OFF_MAX);
}
void
xfs_initialize_vnode(
bhv_desc_t *bdp,
xfs_vnode_t *xvp,
bhv_desc_t *inode_bhv,
int unlock)
{
xfs_inode_t *ip = XFS_BHVTOI(inode_bhv);
if (!inode_bhv->bd_vobj) {
xvp->v_vfsp = bhvtovfs(bdp);
bhv_desc_init(inode_bhv, ip, xvp, &xfs_vnodeops);
bhv_insert(VN_BHV_HEAD(xvp), inode_bhv);
}
/*
* XXX: Use VNON as an indication of freshly allocated vnode
* which need to be initialized and unlocked.
* This is _not_ like the same place in Linux version of
* routine.
*/
if (xvp->v_vnode->v_type != VNON)
return;
xvp->v_vnode->v_type = IFTOVT(ip->i_d.di_mode);
if (xvp->v_vnode->v_type == VFIFO)
xvp->v_vnode->v_op = &xfs_fifoops;
ASSERT_VOP_LOCKED(xvp->v_vnode, "xfs_initialize_vnode");
/* For new inodes we need to set the ops vectors,
* and unlock the inode.
*/
if (ip->i_d.di_mode != 0 && unlock)
VOP_UNLOCK(xvp->v_vnode, 0);
}
#if 0
struct vnode *
xfs_get_inode(
bhv_desc_t *bdp,
xfs_ino_t ino,
int flags)
{
return NULL;
}
#endif
/*ARGSUSED*/
int
xfs_blkdev_get(
xfs_mount_t *mp,
const char *name,
struct vnode **bdevp)
{
struct nameidata nd;
struct nameidata *ndp = &nd;
int error, ronly;
struct thread *td;
struct vnode *devvp;
struct g_consumer *cp;
struct g_provider *pp;
accmode_t accmode;
td = curthread;
NDINIT(ndp, LOOKUP, FOLLOW, UIO_SYSSPACE, name, td);
if ((error = namei(ndp)) != 0)
return (error);
NDFREE(ndp, NDF_ONLY_PNBUF);
devvp = ndp->ni_vp;
if (!vn_isdisk(devvp, &error)) {
vrele(devvp);
return (error);
}
vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY);
ronly = ((XFS_MTOVFS(mp)->vfs_flag & VFS_RDONLY) != 0);
accmode = VREAD;
if (!ronly)
accmode |= VWRITE;
error = VOP_ACCESS(devvp, accmode, td->td_ucred, td);
if (error)
error = priv_check(td, PRIV_VFS_MOUNT_PERM);
if (error) {
vput(devvp);
return (error);
}
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 bmemfree() when you try to
* mount the same device more than once.
* During mounting, XFS does a bread() of the superblock, but does
* not brelse() it. A subsequent mount of the same device
* will try to bread() the superblock, resulting in a panic in
* bremfree(), "buffer not on queue".
*/
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, "xfs", ronly ? 0 : 1);
g_topology_unlock();
PICKUP_GIANT();
if (error) {
vput(devvp);
return (error);
}
VOP_UNLOCK(devvp, 0);
devvp->v_bufobj.bo_private = cp;
devvp->v_bufobj.bo_ops = &xfs_bo_ops;
*bdevp = devvp;
return (0);
}
void
xfs_blkdev_put(
struct vnode *devvp)
{
struct g_consumer *cp;
if (devvp == NULL)
return;
vinvalbuf(devvp, V_SAVE, 0, 0);
cp = devvp->v_bufobj.bo_private;
DROP_GIANT();
g_topology_lock();
g_wither_geom_close(cp->geom, ENXIO);
g_topology_unlock();
PICKUP_GIANT();
vrele(devvp);
}
void
xfs_mountfs_check_barriers(xfs_mount_t *mp)
{
printf("xfs_mountfs_check_barriers NI\n");
}
void
xfs_flush_inode(
xfs_inode_t *ip)
{
printf("xfs_flush_inode NI\n");
}
void
xfs_flush_device(
xfs_inode_t *ip)
{
printf("xfs_flush_device NI\n");
xfs_log_force(ip->i_mount, (xfs_lsn_t)0, XFS_LOG_FORCE|XFS_LOG_SYNC);
}
void
xfs_blkdev_issue_flush(
xfs_buftarg_t *buftarg)
{
printf("xfs_blkdev_issue_flush NI\n");
}
int
init_xfs_fs( void )
{
static const char message[] =
XFS_VERSION_STRING " with " XFS_BUILD_OPTIONS " enabled\n";
printf(message);
vn_init();
xfs_init();
uuid_init();
#ifdef RMC
vfs_initdmapi();
#endif
vfs_initquota();
return 0;
}
void
exit_xfs_fs(void)
{
xfs_cleanup();
vfs_exitquota();
#ifdef RMC
vfs_exitdmapi();
#endif
}

View File

@ -1,113 +0,0 @@
/*
* Copyright (c) 2000-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
*/
#ifndef __XFS_SUPER_H__
#define __XFS_SUPER_H__
#ifdef CONFIG_XFS_DMAPI
# define vfs_insertdmapi(vfs) vfs_insertops(vfsp, &xfs_dmops)
# define vfs_initdmapi() dmapi_init()
# define vfs_exitdmapi() dmapi_uninit()
#else
# define vfs_insertdmapi(vfs) do { } while (0)
# define vfs_initdmapi() do { } while (0)
# define vfs_exitdmapi() do { } while (0)
#endif
#ifdef CONFIG_XFS_QUOTA
# define vfs_insertquota(vfs) vfs_insertops(vfsp, &xfs_qmops)
# define vfs_initquota() xfs_qm_init()
# define vfs_exitquota() xfs_qm_exit()
#else
# define vfs_insertquota(vfs) do { } while (0)
# define vfs_initquota() do { } while (0)
# define vfs_exitquota() do { } while (0)
#endif
#ifdef CONFIG_XFS_POSIX_ACL
# define XFS_ACL_STRING "ACLs, "
# define set_posix_acl_flag(sb) ((sb)->s_flags |= MS_POSIXACL)
#else
# define XFS_ACL_STRING
# define set_posix_acl_flag(sb) do { } while (0)
#endif
#ifdef CONFIG_XFS_SECURITY
# define XFS_SECURITY_STRING "security attributes, "
# define ENOSECURITY 0
#else
# define XFS_SECURITY_STRING
# define ENOSECURITY EOPNOTSUPP
#endif
#ifdef CONFIG_XFS_RT
# define XFS_REALTIME_STRING "realtime, "
#else
# define XFS_REALTIME_STRING
#endif
#if XFS_BIG_BLKNOS
# if XFS_BIG_INUMS
# define XFS_BIGFS_STRING "large block/inode numbers, "
# else
# define XFS_BIGFS_STRING "large block numbers, "
# endif
#else
# define XFS_BIGFS_STRING
#endif
#ifdef CONFIG_XFS_TRACE
# define XFS_TRACE_STRING "tracing, "
#else
# define XFS_TRACE_STRING
#endif
#ifdef XFSDEBUG
# define XFS_DBG_STRING "debug"
#else
# define XFS_DBG_STRING "no debug"
#endif
#define XFS_BUILD_OPTIONS XFS_ACL_STRING \
XFS_SECURITY_STRING \
XFS_REALTIME_STRING \
XFS_BIGFS_STRING \
XFS_TRACE_STRING \
XFS_DBG_STRING /* DBG must be last */
struct xfs_inode;
struct xfs_mount;
struct xfs_buftarg;
extern __uint64_t xfs_max_file_offset(unsigned int);
extern void xfs_initialize_vnode(bhv_desc_t *, xfs_vnode_t *, bhv_desc_t *, int);
extern void xfs_flush_inode(struct xfs_inode *);
extern void xfs_flush_device(struct xfs_inode *);
extern int xfs_blkdev_get(struct xfs_mount *, const char *,
struct block_device **);
extern void xfs_blkdev_put(struct block_device *);
extern void xfs_blkdev_issue_flush(struct xfs_buftarg *);
extern struct export_operations xfs_export_operations;
extern int init_xfs_fs(void);
extern void exit_xfs_fs(void);
#endif /* __XFS_SUPER_H__ */

View File

@ -1,43 +0,0 @@
/*
* Copyright (c) 2001-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/
*/
#include "xfs.h"
void
xfs_sysctl_register(void)
{
}
void
xfs_sysctl_unregister(void)
{
}

View File

@ -1,102 +0,0 @@
/*
* Copyright (c) 2001-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
*/
#ifndef __XFS_SYSCTL_H__
#define __XFS_SYSCTL_H__
/*
* Tunable xfs parameters
*/
typedef struct xfs_sysctl_val {
int min;
int val;
int max;
} xfs_sysctl_val_t;
typedef struct xfs_param {
xfs_sysctl_val_t refcache_size; /* Size of NFS reference cache. */
xfs_sysctl_val_t refcache_purge;/* # of entries to purge each time. */
xfs_sysctl_val_t restrict_chown;/* Root/non-root can give away files.*/
xfs_sysctl_val_t sgid_inherit; /* Inherit S_ISGID if process' GID is
* not a member of parent dir GID. */
xfs_sysctl_val_t symlink_mode; /* Link creat mode affected by umask */
xfs_sysctl_val_t panic_mask; /* bitmask to cause panic on errors. */
xfs_sysctl_val_t error_level; /* Degree of reporting for problems */
xfs_sysctl_val_t syncd_timer; /* Interval between xfssyncd wakeups */
xfs_sysctl_val_t stats_clear; /* Reset all XFS statistics to zero. */
xfs_sysctl_val_t probe_dmapi; /* probe for DMAPI module on mount. */
xfs_sysctl_val_t probe_ioops; /* probe for an IO module on mount. */
xfs_sysctl_val_t probe_quota; /* probe for quota module on mount. */
xfs_sysctl_val_t inherit_sync; /* Inherit the "sync" inode flag. */
xfs_sysctl_val_t inherit_nodump;/* Inherit the "nodump" inode flag. */
xfs_sysctl_val_t inherit_noatim;/* Inherit the "noatime" inode flag. */
xfs_sysctl_val_t xfs_buf_timer; /* Interval between xfsbufd wakeups. */
xfs_sysctl_val_t xfs_buf_age; /* Metadata buffer age before flush. */
xfs_sysctl_val_t inherit_nosym; /* Inherit the "nosymlinks" flag. */
xfs_sysctl_val_t rotorstep; /* inode32 AG rotoring control knob */
} xfs_param_t;
/*
* xfs_error_level:
*
* How much error reporting will be done when internal problems are
* encountered. These problems normally return an EFSCORRUPTED to their
* caller, with no other information reported.
*
* 0 No error reports
* 1 Report EFSCORRUPTED errors that will cause a filesystem shutdown
* 5 Report all EFSCORRUPTED errors (all of the above errors, plus any
* additional errors that are known to not cause shutdowns)
*
* xfs_panic_mask bit 0x8 turns the error reports into panics
*/
enum {
/* XFS_REFCACHE_SIZE = 1 */
/* XFS_REFCACHE_PURGE = 2 */
XFS_RESTRICT_CHOWN = 3,
XFS_SGID_INHERIT = 4,
XFS_SYMLINK_MODE = 5,
XFS_PANIC_MASK = 6,
XFS_ERRLEVEL = 7,
XFS_SYNCD_TIMER = 8,
XFS_PROBE_DMAPI = 9,
XFS_PROBE_IOOPS = 10,
XFS_PROBE_QUOTA = 11,
XFS_STATS_CLEAR = 12,
XFS_INHERIT_SYNC = 13,
XFS_INHERIT_NODUMP = 14,
XFS_INHERIT_NOATIME = 15,
XFS_BUF_TIMER = 16,
XFS_BUF_AGE = 17,
/* XFS_IO_BYPASS = 18 */
XFS_INHERIT_NOSYM = 19,
XFS_ROTORSTEP = 20,
};
extern xfs_param_t xfs_params;
#ifdef CONFIG_SYSCTL
extern void xfs_sysctl_register(void);
extern void xfs_sysctl_unregister(void);
#else
# define xfs_sysctl_register() do { } while (0)
# define xfs_sysctl_unregister() do { } while (0)
#endif /* CONFIG_SYSCTL */
#endif /* __XFS_SYSCTL_H__ */

View File

@ -1,44 +0,0 @@
/*
* Copyright (c) 2001-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/
*/
/*
* Dummy file that can contain a timestamp to put into the
* XFS init string, to help users keep track of what they're
* running
*/
#ifndef __XFS_VERSION_H__
#define __XFS_VERSION_H__
#define XFS_VERSION_STRING "SGI XFS"
#endif /* __XFS_VERSION_H__ */

View File

@ -1,356 +0,0 @@
/*
* Copyright (c) 2000-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"
#include "xfs_fs.h"
#include "xfs_inum.h"
#include "xfs_log.h"
#include "xfs_clnt.h"
#include "xfs_trans.h"
#include "xfs_sb.h"
#include "xfs_ag.h"
#include "xfs_dir.h"
#include "xfs_dir2.h"
#include "xfs_imap.h"
#include "xfs_alloc.h"
#include "xfs_dmapi.h"
#include "xfs_mount.h"
#include "xfs_quota.h"
#include "xfs_mountops.h"
int
xvfs_mount(
struct bhv_desc *bdp,
struct xfs_mount_args *args,
struct cred *cr)
{
struct bhv_desc *next = bdp;
ASSERT(next);
while (! (bhvtovfsops(next))->xvfs_mount)
next = BHV_NEXT(next);
return ((*bhvtovfsops(next)->xvfs_mount)(next, args, cr));
}
int
xvfs_parseargs(
struct bhv_desc *bdp,
char *s,
struct xfs_mount_args *args,
int f)
{
struct bhv_desc *next = bdp;
ASSERT(next);
while (! (bhvtovfsops(next))->xvfs_parseargs)
next = BHV_NEXT(next);
return ((*bhvtovfsops(next)->xvfs_parseargs)(next, s, args, f));
}
int
xvfs_showargs(
struct bhv_desc *bdp,
struct sbuf *m)
{
struct bhv_desc *next = bdp;
ASSERT(next);
while (! (bhvtovfsops(next))->xvfs_showargs)
next = BHV_NEXT(next);
return ((*bhvtovfsops(next)->xvfs_showargs)(next, m));
}
int
xvfs_unmount(
struct bhv_desc *bdp,
int fl,
struct cred *cr)
{
struct bhv_desc *next = bdp;
ASSERT(next);
while (! (bhvtovfsops(next))->xvfs_unmount)
next = BHV_NEXT(next);
return ((*bhvtovfsops(next)->xvfs_unmount)(next, fl, cr));
}
int
xvfs_mntupdate(
struct bhv_desc *bdp,
int *fl,
struct xfs_mount_args *args)
{
struct bhv_desc *next = bdp;
ASSERT(next);
while (! (bhvtovfsops(next))->xvfs_mntupdate)
next = BHV_NEXT(next);
return ((*bhvtovfsops(next)->xvfs_mntupdate)(next, fl, args));
}
int
xvfs_root(
struct bhv_desc *bdp,
struct xfs_vnode **vpp)
{
struct bhv_desc *next = bdp;
ASSERT(next);
while (! (bhvtovfsops(next))->xvfs_root)
next = BHV_NEXT(next);
return ((*bhvtovfsops(next)->xvfs_root)(next, vpp));
}
int
xvfs_statvfs(
struct bhv_desc *bdp,
struct statfs *sp,
struct xfs_vnode *vp)
{
struct bhv_desc *next = bdp;
ASSERT(next);
while (! (bhvtovfsops(next))->xvfs_statvfs)
next = BHV_NEXT(next);
return ((*bhvtovfsops(next)->xvfs_statvfs)(next, sp, vp));
}
int
xvfs_sync(
struct bhv_desc *bdp,
int fl,
struct cred *cr)
{
struct bhv_desc *next = bdp;
ASSERT(next);
while (! (bhvtovfsops(next))->xvfs_sync)
next = BHV_NEXT(next);
return ((*bhvtovfsops(next)->xvfs_sync)(next, fl, cr));
}
int
xvfs_vget(
struct bhv_desc *bdp,
struct xfs_vnode **vpp,
struct fid *fidp)
{
struct bhv_desc *next = bdp;
ASSERT(next);
while (! (bhvtovfsops(next))->xvfs_vget)
next = BHV_NEXT(next);
return ((*bhvtovfsops(next)->xvfs_vget)(next, vpp, fidp));
}
int
xvfs_dmapiops(
struct bhv_desc *bdp,
caddr_t addr)
{
struct bhv_desc *next = bdp;
ASSERT(next);
while (! (bhvtovfsops(next))->xvfs_dmapiops)
next = BHV_NEXT(next);
return ((*bhvtovfsops(next)->xvfs_dmapiops)(next, addr));
}
int
xvfs_quotactl(
struct bhv_desc *bdp,
int cmd,
int id,
caddr_t addr)
{
struct bhv_desc *next = bdp;
ASSERT(next);
while (! (bhvtovfsops(next))->xvfs_quotactl)
next = BHV_NEXT(next);
return ((*bhvtovfsops(next)->xvfs_quotactl)(next, cmd, id, addr));
}
struct inode *
xvfs_get_inode(
struct bhv_desc *bdp,
xfs_ino_t ino,
int fl)
{
struct bhv_desc *next = bdp;
while (! (bhvtovfsops(next))->xvfs_get_inode)
next = BHV_NEXTNULL(next);
return ((*bhvtovfsops(next)->xvfs_get_inode)(next, ino, fl));
}
void
xvfs_init_vnode(
struct bhv_desc *bdp,
struct xfs_vnode *vp,
struct bhv_desc *bp,
int unlock)
{
struct bhv_desc *next = bdp;
ASSERT(next);
while (! (bhvtovfsops(next))->xvfs_init_vnode)
next = BHV_NEXT(next);
((*bhvtovfsops(next)->xvfs_init_vnode)(next, vp, bp, unlock));
}
void
xvfs_force_shutdown(
struct bhv_desc *bdp,
int fl,
char *file,
int line)
{
struct bhv_desc *next = bdp;
ASSERT(next);
while (! (bhvtovfsops(next))->xvfs_force_shutdown)
next = BHV_NEXT(next);
((*bhvtovfsops(next)->xvfs_force_shutdown)(next, fl, file, line));
}
xfs_vfs_t *
vfs_allocate(struct mount *mp)
{
struct xfs_vfs *vfsp;
struct xfsmount *xmp;
xmp = kmem_zalloc(sizeof(*xmp), KM_SLEEP);
vfsp = XFSTOVFS(xmp);
bhv_head_init(VFS_BHVHEAD(vfsp), "vfs");
xmp->m_mp = mp;
mp->mnt_data = xmp;
vfsp->vfs_mp = mp;
return vfsp;
}
void
vfs_deallocate(
struct xfs_vfs *vfsp)
{
struct xfsmount *xmp;
bhv_head_destroy(VFS_BHVHEAD(vfsp));
xmp = VFSTOXFS(vfsp);
kmem_free(xmp, sizeof(*xmp));
}
/*
* Allocate and initialize a new XFS mount structure
*/
struct xfsmount *
xfsmount_allocate(struct mount *mp)
{
xfs_vfs_t *vfsp;
vfsp = vfs_allocate(mp);
ASSERT(vfsp);
if (mp->mnt_flag & MNT_RDONLY)
vfsp->vfs_flag |= VFS_RDONLY;
bhv_insert_all_vfsops(vfsp);
return (VFSTOXFS(vfsp));
}
void
xfsmount_deallocate(struct xfsmount *xmp)
{
xfs_vfs_t *vfsp;
vfsp = XFSTOVFS(xmp);
bhv_remove_all_vfsops(vfsp, 1);
vfs_deallocate(vfsp);
}
void
vfs_insertops(
struct xfs_vfs *vfsp,
struct bhv_vfsops *vfsops)
{
struct bhv_desc *bdp;
bdp = kmem_alloc(sizeof(struct bhv_desc), KM_SLEEP);
bhv_desc_init(bdp, NULL, vfsp, vfsops);
bhv_insert(&vfsp->vfs_bh, bdp);
}
void
vfs_insertbhv(
struct xfs_vfs *vfsp,
struct bhv_desc *bdp,
struct xvfsops *vfsops,
void *mount)
{
bhv_desc_init(bdp, mount, vfsp, vfsops);
bhv_insert_initial(&vfsp->vfs_bh, bdp);
}
void
bhv_remove_vfsops(
struct xfs_vfs *vfsp,
int pos)
{
struct bhv_desc *bhv;
bhv = bhv_lookup_range(&vfsp->vfs_bh, pos, pos);
if (bhv) {
bhv_remove(&vfsp->vfs_bh, bhv);
kmem_free(bhv, sizeof(*bhv));
}
}
void
bhv_remove_all_vfsops(
struct xfs_vfs *vfsp,
int freebase)
{
struct xfs_mount *mp;
bhv_remove_vfsops(vfsp, VFS_POSITION_QM);
bhv_remove_vfsops(vfsp, VFS_POSITION_DM);
bhv_remove_vfsops(vfsp, VFS_POSITION_IO);
if (!freebase)
return;
mp = XFS_BHVTOM(bhv_lookup(VFS_BHVHEAD(vfsp), &xfs_vfsops));
VFS_REMOVEBHV(vfsp, &mp->m_bhv);
xfs_mount_free(mp, 0);
}
void
bhv_insert_all_vfsops(
struct xfs_vfs *vfsp)
{
struct xfs_mount *mp;
mp = xfs_mount_init();
vfs_insertbhv(vfsp, &mp->m_bhv, &xfs_vfsops, mp);
vfs_insertdmapi(vfsp);
vfs_insertquota(vfsp);
}

View File

@ -1,232 +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_VFS_H__
#define __XFS_VFS_H__
#include <sys/mount.h>
#include "xfs_fs.h"
struct fid;
struct cred;
struct xfs_vnode;
struct statfs;
struct sbuf;
struct xfs_mount_args;
struct mount;
typedef struct statfs xfs_statfs_t;
typedef struct xfs_vfs {
u_int vfs_flag; /* flags */
xfs_fsid_t vfs_fsid; /* file system ID */
xfs_fsid_t *vfs_altfsid; /* An ID fixed for life of FS */
bhv_head_t vfs_bh; /* head of vfs behavior chain */
struct mount *vfs_mp; /* FreeBSD mount struct */
} xfs_vfs_t;
#define MNTTOXVFS(mp) ((struct xfs_vfs*)(mp)->mnt_data)
#define XVFSTOMNT(vfs) ((vfs)->vfs_mp)
#define vfs_fbhv vfs_bh.bh_first /* 1st on vfs behavior chain */
#define bhvtovfs(bdp) ( (struct xfs_vfs *)BHV_VOBJ(bdp) )
#define bhvtovfsops(bdp) ( (struct xvfsops *)BHV_OPS(bdp) )
#define VFS_BHVHEAD(vfs) ( &(vfs)->vfs_bh )
#define VFS_REMOVEBHV(vfs, bdp) ( bhv_remove(VFS_BHVHEAD(vfs), bdp) )
#define VFS_POSITION_BASE BHV_POSITION_BASE /* chain bottom */
#define VFS_POSITION_TOP BHV_POSITION_TOP /* chain top */
#define VFS_POSITION_INVALID BHV_POSITION_INVALID /* invalid pos. num */
typedef enum {
VFS_BHV_UNKNOWN, /* not specified */
VFS_BHV_XFS, /* xfs */
VFS_BHV_DM, /* data migration */
VFS_BHV_QM, /* quota manager */
VFS_BHV_IO, /* IO path */
VFS_BHV_END /* housekeeping end-of-range */
} vfs_bhv_t;
#define VFS_POSITION_XFS (BHV_POSITION_BASE)
#define VFS_POSITION_DM (VFS_POSITION_BASE+10)
#define VFS_POSITION_QM (VFS_POSITION_BASE+20)
#define VFS_POSITION_IO (VFS_POSITION_BASE+30)
#define VFS_RDONLY 0x0001 /* read-only vfs */
#define VFS_GRPID 0x0002 /* group-ID assigned from directory */
#define VFS_DMI 0x0004 /* filesystem has the DMI enabled */
#define VFS_32BITINODES 0x0008 /* do not use inums above 32 bits */
#define VFS_END 0x0008 /* max flag */
#define SYNC_ATTR 0x0001 /* sync attributes */
#define SYNC_CLOSE 0x0002 /* close file system down */
#define SYNC_DELWRI 0x0004 /* look at delayed writes */
#define SYNC_WAIT 0x0008 /* wait for i/o to complete */
#define SYNC_BDFLUSH 0x0010 /* BDFLUSH is calling -- don't block */
#define SYNC_FSDATA 0x0020 /* flush fs data (e.g. superblocks) */
#define SYNC_REFCACHE 0x0040 /* prune some of the nfs ref cache */
#define SYNC_REMOUNT 0x0080 /* remount readonly, no dummy LRs */
#define SYNC_QUIESCE 0x0100 /* quiesce filesystem for a snapshot */
#define IGET_NOALLOC 0x0001 /* vfs_get_inode may return NULL */
typedef int (*xvfs_mount_t)(bhv_desc_t *,
struct xfs_mount_args *, struct cred *);
typedef int (*xvfs_parseargs_t)(bhv_desc_t *, char *,
struct xfs_mount_args *, int);
typedef int (*xvfs_showargs_t)(bhv_desc_t *, struct sbuf *);
typedef int (*xvfs_unmount_t)(bhv_desc_t *, int, struct cred *);
typedef int (*xvfs_mntupdate_t)(bhv_desc_t *, int *,
struct xfs_mount_args *);
typedef int (*xvfs_root_t)(bhv_desc_t *, struct xfs_vnode **);
typedef int (*xvfs_statvfs_t)(bhv_desc_t *, xfs_statfs_t *, struct xfs_vnode *);
typedef int (*xvfs_sync_t)(bhv_desc_t *, int, struct cred *);
typedef int (*xvfs_vget_t)(bhv_desc_t *, struct xfs_vnode **, struct fid *);
typedef int (*xvfs_dmapiops_t)(bhv_desc_t *, caddr_t);
typedef int (*xvfs_quotactl_t)(bhv_desc_t *, int, int, caddr_t);
typedef void (*xvfs_init_vnode_t)(bhv_desc_t *,
struct xfs_vnode *, bhv_desc_t *, int);
typedef void (*xvfs_force_shutdown_t)(bhv_desc_t *, int, char *, int);
typedef struct inode * (*xvfs_get_inode_t)(bhv_desc_t *, xfs_ino_t, int);
typedef void (*xvfs_freeze_t)(bhv_desc_t *);
typedef struct xvfsops {
bhv_position_t xvfs_position; /* behavior chain position */
xvfs_mount_t xvfs_mount; /* mount file system */
xvfs_parseargs_t xvfs_parseargs; /* parse mount options */
xvfs_showargs_t xvfs_showargs; /* unparse mount options */
xvfs_unmount_t xvfs_unmount; /* unmount file system */
xvfs_mntupdate_t xvfs_mntupdate; /* update file system options */
xvfs_root_t xvfs_root; /* get root vnode */
xvfs_statvfs_t xvfs_statvfs; /* file system statistics */
xvfs_sync_t xvfs_sync; /* flush files */
xvfs_vget_t xvfs_vget; /* get vnode from fid */
xvfs_dmapiops_t xvfs_dmapiops; /* data migration */
xvfs_quotactl_t xvfs_quotactl; /* disk quota */
xvfs_get_inode_t xvfs_get_inode; /* bhv specific iget */
xvfs_init_vnode_t xvfs_init_vnode; /* initialize a new vnode */
xvfs_force_shutdown_t xvfs_force_shutdown; /* crash and burn */
xvfs_freeze_t xvfs_freeze; /* freeze fs for snapshot */
} xvfsops_t;
/*
* VFS's. Operates on vfs structure pointers (starts at bhv head).
*/
#define VHEAD(v) ((v)->vfs_fbhv)
#define XVFS_MOUNT(v, ma,cr, rv) ((rv) = xvfs_mount(VHEAD(v), ma,cr))
#define XVFS_PARSEARGS(v, o,ma,f, rv) ((rv) = xvfs_parseargs(VHEAD(v), o,ma,f))
#define XVFS_SHOWARGS(v, m, rv) ((rv) = xvfs_showargs(VHEAD(v), m))
#define XVFS_UNMOUNT(v, f, cr, rv) ((rv) = xvfs_unmount(VHEAD(v), f,cr))
#define XVFS_MNTUPDATE(v, fl, args, rv) ((rv) = xvfs_mntupdate(VHEAD(v), fl, args))
#define XVFS_ROOT(v, vpp, rv) ((rv) = xvfs_root(VHEAD(v), vpp))
#define XVFS_STATVFS(v, sp,vp, rv) ((rv) = xvfs_statvfs(VHEAD(v), sp,vp))
#define XVFS_SYNC(v, flag,cr, rv) ((rv) = xvfs_sync(VHEAD(v), flag,cr))
#define XVFS_VGET(v, vpp,fidp, rv) ((rv) = xvfs_vget(VHEAD(v), vpp,fidp))
#define XVFS_DMAPIOPS(v, p, rv) ((rv) = xvfs_dmapiops(VHEAD(v), p))
#define XVFS_QUOTACTL(v, c,id,p, rv) ((rv) = xvfs_quotactl(VHEAD(v), c,id,p))
#define XVFS_GET_INODE(v, ino, fl) ( xvfs_get_inode(VHEAD(v), ino,fl) )
#define XVFS_INIT_VNODE(v, vp,b,ul) ( xvfs_init_vnode(VHEAD(v), vp,b,ul) )
#define XVFS_FORCE_SHUTDOWN(v, fl,f,l) ( xvfs_force_shutdown(VHEAD(v), fl,f,l) )
/*
* PVFS's. Operates on behavior descriptor pointers.
*/
#define PVFS_MOUNT(b, ma,cr, rv) ((rv) = xvfs_mount(b, ma,cr))
#define PVFS_PARSEARGS(b, o,ma,f, rv) ((rv) = xvfs_parseargs(b, o,ma,f))
#define PVFS_SHOWARGS(b, m, rv) ((rv) = xvfs_showargs(b, m))
#define PVFS_UNMOUNT(b, f,cr, rv) ((rv) = xvfs_unmount(b, f,cr))
#define PVFS_MNTUPDATE(b, fl, args, rv) ((rv) = xvfs_mntupdate(b, fl, args))
#define PVFS_ROOT(b, vpp, rv) ((rv) = xvfs_root(b, vpp))
#define PVFS_STATVFS(b, sp,vp, rv) ((rv) = xvfs_statvfs(b, sp,vp))
#define PVFS_SYNC(b, flag,cr, rv) ((rv) = xvfs_sync(b, flag,cr))
#define PVFS_VGET(b, vpp,fidp, rv) ((rv) = xvfs_vget(b, vpp,fidp))
#define PVFS_DMAPIOPS(b, p, rv) ((rv) = xvfs_dmapiops(b, p))
#define PVFS_QUOTACTL(b, c,id,p, rv) ((rv) = xvfs_quotactl(b, c,id,p))
#define PVFS_GET_INODE(b, ino,fl) ( xvfs_get_inode(b, ino,fl) )
#define PVFS_INIT_VNODE(b, vp,b2,ul) ( xvfs_init_vnode(b, vp,b2,ul) )
#define PVFS_FORCE_SHUTDOWN(b, fl,f,l) ( xvfs_force_shutdown(b, fl,f,l) )
extern int xvfs_mount(bhv_desc_t *, struct xfs_mount_args *, struct cred *);
extern int xvfs_parseargs(bhv_desc_t *, char *, struct xfs_mount_args *, int);
extern int xvfs_showargs(bhv_desc_t *, struct sbuf *);
extern int xvfs_unmount(bhv_desc_t *, int, struct cred *);
extern int xvfs_mntupdate(bhv_desc_t *, int *, struct xfs_mount_args *);
extern int xvfs_root(bhv_desc_t *, struct xfs_vnode **);
extern int xvfs_statvfs(bhv_desc_t *, xfs_statfs_t *, struct xfs_vnode *);
extern int xvfs_sync(bhv_desc_t *, int, struct cred *);
extern int xvfs_vget(bhv_desc_t *, struct xfs_vnode **, struct fid *);
extern int xvfs_dmapiops(bhv_desc_t *, caddr_t);
extern int xvfs_quotactl(bhv_desc_t *, int, int, caddr_t);
extern struct inode *xvfs_get_inode(bhv_desc_t *, xfs_ino_t, int);
extern void xvfs_init_vnode(bhv_desc_t *, struct xfs_vnode *, bhv_desc_t *, int);
extern void xvfs_force_shutdown(bhv_desc_t *, int, char *, int);
#define XFS_DMOPS "xfs_dm_operations" /* Data Migration */
#define XFS_QMOPS "xfs_qm_operations" /* Quota Manager */
#define XFS_IOOPS "xfs_io_operations" /* I/O subsystem */
#define XFS_DM_MODULE "xfs_dmapi"
#define XFS_QM_MODULE "xfs_quota"
#define XFS_IO_MODULE "xfs_ioops"
typedef struct bhv_vfsops {
struct xvfsops bhv_common;
void * bhv_custom;
} bhv_vfsops_t;
typedef struct bhv_module {
bhv_desc_t bm_desc;
const char * bm_name;
bhv_vfsops_t * bm_ops;
} bhv_module_t;
#define vfs_bhv_lookup(v, id) ( bhv_lookup_range(&(v)->vfs_bh, (id), (id)) )
#define vfs_bhv_custom(b) ( ((bhv_vfsops_t *)BHV_OPS(b))->bhv_custom )
#define vfs_bhv_set_custom(b,o) ( (b)->bhv_custom = (void *)(o))
#define vfs_bhv_clr_custom(b) ( (b)->bhv_custom = NULL )
extern xfs_vfs_t *vfs_allocate(struct mount *);
extern void vfs_deallocate(xfs_vfs_t *);
extern void vfs_insertops(xfs_vfs_t *, bhv_vfsops_t *);
extern void vfs_insertbhv(xfs_vfs_t *, bhv_desc_t *, xvfsops_t *, void *);
#define bhv_lookup_module(n,m) ( (m) ? \
inter_module_get_request(n, m) : \
inter_module_get(n) )
#define bhv_remove_module(n) inter_module_put(n)
#define bhv_module_init(n,m,op) inter_module_register(n,m,op)
#define bhv_module_exit(n) inter_module_unregister(n)
extern void bhv_insert_all_vfsops(struct xfs_vfs *);
extern void bhv_remove_all_vfsops(struct xfs_vfs *, int);
extern void bhv_remove_vfsops(struct xfs_vfs *, int);
#endif /* __XFS_VFS_H__ */

View File

@ -1,272 +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.h"
#include "xfs_types.h"
#include "xfs_bit.h"
#include "xfs_inum.h"
#include "xfs_log.h"
#include "xfs_trans.h"
#include "xfs_trans_priv.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_alloc_btree.h"
#include "xfs_bmap_btree.h"
#include "xfs_ialloc_btree.h"
#include "xfs_btree.h"
#include "xfs_imap.h"
#include "xfs_alloc.h"
#include "xfs_attr_sf.h"
#include "xfs_dir_sf.h"
#include "xfs_dir2_sf.h"
#include "xfs_dinode.h"
#include "xfs_ialloc.h"
#include "xfs_inode.h"
#include "xfs_inode_item.h"
void
vn_init(void)
{
}
void
vn_iowait(
struct xfs_vnode *vp)
{
printf("vn_iowait doing nothing on FreeBSD?\n");
}
struct xfs_vnode *
vn_initialize(
xfs_vnode_t *vp)
{
XFS_STATS_INC(vn_active);
XFS_STATS_INC(vn_alloc);
/* Initialize the first behavior and the behavior chain head. */
vn_bhv_head_init(VN_BHV_HEAD(vp), "vnode");
#ifdef CONFIG_XFS_VNODE_TRACING
vp->v_trace = ktrace_alloc(VNODE_TRACE_SIZE, KM_SLEEP);
#endif /* CONFIG_XFS_VNODE_TRACING */
vn_trace_exit(vp, "vn_initialize", (inst_t *)__return_address);
return vp;
}
/*
* Get a reference on a vnode. Need to drop vnode reference
* to accomodate for vhold by VMAP regardless of whether or
* not we were able to successfully grab the vnode.
*/
xfs_vnode_t *
vn_get(
struct xfs_vnode *xfs_vp,
vmap_t *vmap)
{
struct vnode *vp;
int error;
XFS_STATS_INC(vn_get);
vp = vmap->v_vp;
error = vget(vp, LK_EXCLUSIVE, curthread);
vdrop(vp);
if (error)
return (NULL);
/*
* Drop the vnode returned by vget here.
* VOP_RECLAIM(9) should block on internal XFS locks so that
* the reclaiming scheme still remains consistent even if the
* vp is not locked.
*/
VOP_UNLOCK(vp, 0);
if (vp->v_data != xfs_vp) {
vput(vp);
return (NULL);
}
vn_trace_exit(vp, "vn_get", (inst_t *)__return_address);
return xfs_vp;
}
/*
* purge a vnode from the cache
* At this point the vnode is guaranteed to have no references (vn_count == 0)
* The caller has to make sure that there are no ways someone could
* get a handle (via vn_get) on the vnode (usually done via a mount/vfs lock).
*/
void
vn_purge(struct xfs_vnode *xfs_vp)
{
struct vnode *vp;
vn_trace_entry(vp, "vn_purge", (inst_t *)__return_address);
vp = xfs_vp->v_vnode;
vn_lock(vp, LK_EXCLUSIVE);
if (vp->v_holdcnt == 0)
vhold(vp);
vgone(vp);
VOP_UNLOCK(vp, 0);
}
void xfs_ichgtime(
xfs_inode_t *ip,
int flags)
{
timespec_t tv;
vfs_timestamp(&tv);
if (flags & XFS_ICHGTIME_MOD) {
ip->i_d.di_mtime.t_sec = (__int32_t)tv.tv_sec;
ip->i_d.di_mtime.t_nsec = (__int32_t)tv.tv_nsec;
}
if (flags & XFS_ICHGTIME_ACC) {
ip->i_d.di_atime.t_sec = (__int32_t)tv.tv_sec;
ip->i_d.di_atime.t_nsec = (__int32_t)tv.tv_nsec;
}
if (flags & XFS_ICHGTIME_CHG) {
ip->i_d.di_ctime.t_sec = (__int32_t)tv.tv_sec;
ip->i_d.di_ctime.t_nsec = (__int32_t)tv.tv_nsec;
}
//printf ("xfs_ichgtime NI\n");
}
/*
* Bring the atime in the XFS inode uptodate.
* Used before logging the inode to disk or when the Linux inode goes away.
*/
/*
* It's unclear if we need this since this is for syncing the linux inode's atime
* to the xfs inode's atime.
* Since FreeBSD doesn't have atime in the vnode is there anything to really
* sync over?
* For now just make this a update atime call
*/
void
xfs_synchronize_atime(
xfs_inode_t *ip)
{
#if 0
xfs_vnode_t *vp;
#endif
timespec_t tv;
/* vfs_timestamp looks at the system time accuracy variable */
vfs_timestamp(&tv);
#if 0
printf("xfs_synchronize_atime old (%d,%d) new (%d,%ld)\n",
ip->i_d.di_atime.t_sec,
ip->i_d.di_atime.t_nsec,
tv.tv_sec,
tv.tv_nsec);
#endif
ip->i_d.di_atime.t_sec = (__int32_t)tv.tv_sec;
ip->i_d.di_atime.t_nsec = (__int32_t)tv.tv_nsec;
}
#ifdef RMC
/*
* Extracting atime values in various formats
*/
void vn_atime_to_bstime(struct xfs_vnode *vp, xfs_bstime_t *bs_atime)
{
bs_atime->tv_sec = vp->v_inode.i_atime.tv_sec;
bs_atime->tv_nsec = vp->v_inode.i_atime.tv_nsec;
printf("vn_atime_to_bstime NI\n");
}
#endif
#ifdef CONFIG_XFS_VNODE_TRACING
#define KTRACE_ENTER(vp, vk, s, line, ra) \
ktrace_enter( (vp)->v_trace, \
/* 0 */ (void *)(__psint_t)(vk), \
/* 1 */ (void *)(s), \
/* 2 */ (void *)(__psint_t) line, \
/* 3 */ (void *)(vn_count(vp)), \
/* 4 */ (void *)(ra), \
/* 5 */ (void *)(__psunsigned_t)(vp)->v_flag, \
/* 6 */ (void *)(__psint_t)smp_processor_id(), \
/* 7 */ (void *)(__psint_t)(current->pid), \
/* 8 */ (void *)__return_address, \
/* 9 */ 0, 0, 0, 0, 0, 0, 0)
/*
* Vnode tracing code.
*/
void
vn_trace_entry(xfs_vnode_t *vp, char *func, inst_t *ra)
{
KTRACE_ENTER(vp, VNODE_KTRACE_ENTRY, func, 0, ra);
}
void
vn_trace_exit(xfs_vnode_t *vp, char *func, inst_t *ra)
{
KTRACE_ENTER(vp, VNODE_KTRACE_EXIT, func, 0, ra);
}
void
vn_trace_hold(xfs_vnode_t *vp, char *file, int line, inst_t *ra)
{
KTRACE_ENTER(vp, VNODE_KTRACE_HOLD, file, line, ra);
}
void
vn_trace_ref(xfs_vnode_t *vp, char *file, int line, inst_t *ra)
{
KTRACE_ENTER(vp, VNODE_KTRACE_REF, file, line, ra);
}
void
vn_trace_rele(xfs_vnode_t *vp, char *file, int line, inst_t *ra)
{
KTRACE_ENTER(vp, VNODE_KTRACE_RELE, file, line, ra);
}
#endif /* CONFIG_XFS_VNODE_TRACING */

View File

@ -1,673 +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/
*
* Portions Copyright (c) 1989, 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. 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_VNODE_H__
#define __XFS_VNODE_H__
#include <sys/vnode.h>
#include <sys/namei.h>
struct xfs_iomap;
typedef struct componentname vname_t;
typedef bhv_head_t vn_bhv_head_t;
/*
* MP locking protocols:
* v_flag, v_vfsp VN_LOCK/VN_UNLOCK
* v_type read-only or fs-dependent
*/
typedef struct xfs_vnode {
__u32 v_flag; /* vnode flags (see below) */
struct xfs_vfs *v_vfsp; /* ptr to containing VFS */
xfs_ino_t v_number; /* in-core vnode number */
vn_bhv_head_t v_bh; /* behavior head */
struct vnode *v_vnode; /* FreeBSD vnode */
struct xfs_inode *v_inode; /* XFS inode */
#ifdef XFS_VNODE_TRACE
struct ktrace *v_trace; /* trace header structure */
#endif
} xfs_vnode_t;
/* vnode types */
#define VN_ISLNK(vp) ((vp)->v_vnode->v_type & VLNK)
#define VN_ISREG(vp) ((vp)->v_vnode->v_type & VREG)
#define VN_ISDIR(vp) ((vp)->v_vnode->v_type & VDIR)
#define VN_ISCHR(vp) ((vp)->v_vnode->v_type & VCHR)
#define VN_ISBLK(vp) ((vp)->v_vnode->v_type & VBLK)
#define VN_BAD(vp) ((vp)->v_vnode->v_type & VBAD)
#define v_fbhv v_bh.bh_first /* first behavior */
#define v_fops v_bh.bh_first->bd_ops /* first behavior ops */
#define VNODE_POSITION_BASE BHV_POSITION_BASE /* chain bottom */
#define VNODE_POSITION_TOP BHV_POSITION_TOP /* chain top */
#define VNODE_POSITION_INVALID BHV_POSITION_INVALID /* invalid pos. num */
typedef enum {
VN_BHV_UNKNOWN, /* not specified */
VN_BHV_XFS, /* xfs */
VN_BHV_DM, /* data migration */
VN_BHV_QM, /* quota manager */
VN_BHV_IO, /* IO path */
VN_BHV_END /* housekeeping end-of-range */
} vn_bhv_t;
#define VNODE_POSITION_XFS (VNODE_POSITION_BASE)
#define VNODE_POSITION_DM (VNODE_POSITION_BASE+10)
#define VNODE_POSITION_QM (VNODE_POSITION_BASE+20)
#define VNODE_POSITION_IO (VNODE_POSITION_BASE+30)
#define VPTOXFSVP(vp) ((struct xfs_vnode *)(vp)->v_data)
/*
* Macros for dealing with the behavior descriptor inside of the vnode.
*/
#define BHV_TO_VNODE(bdp) ((xfs_vnode_t *)BHV_VOBJ(bdp))
#define BHV_TO_VNODE_NULL(bdp) ((xfs_vnode_t *)BHV_VOBJNULL(bdp))
#define VN_BHV_HEAD(vp) ((bhv_head_t *)(&((vp)->v_bh)))
#define vn_bhv_head_init(bhp,name) bhv_head_init(bhp,name)
#define vn_bhv_remove(bhp,bdp) bhv_remove(bhp,bdp)
#define vn_bhv_lookup(bhp,ops) bhv_lookup(bhp,ops)
#define vn_bhv_lookup_unlocked(bhp,ops) bhv_lookup_unlocked(bhp,ops)
/*
* Vnode to Linux inode mapping.
*/
#define LINVFS_GET_VP(inode) ((xfs_vnode_t *)NULL)
#define LINVFS_GET_IP(vp) ((xfs_inode_t *)NULL)
/*
* Vnode flags.
*/
#define VINACT 0x1 /* vnode is being inactivated */
#define VRECLM 0x2 /* vnode is being reclaimed */
#define VWAIT 0x4 /* waiting for VINACT/VRECLM to end */
#define VMODIFIED 0x8 /* XFS inode state possibly differs */
/* to the Linux inode state. */
/*
* Values for the VOP_RWLOCK and VOP_RWUNLOCK flags parameter.
*/
typedef enum vrwlock {
VRWLOCK_NONE,
VRWLOCK_READ,
VRWLOCK_WRITE,
VRWLOCK_WRITE_DIRECT,
VRWLOCK_TRY_READ,
VRWLOCK_TRY_WRITE
} vrwlock_t;
/*
* Return values for VOP_INACTIVE. A return value of
* VN_INACTIVE_NOCACHE implies that the file system behavior
* has disassociated its state and bhv_desc_t from the vnode.
*/
#define VN_INACTIVE_CACHE 0
#define VN_INACTIVE_NOCACHE 1
/*
* Values for the cmd code given to VOP_VNODE_CHANGE.
*/
typedef enum vchange {
VCHANGE_FLAGS_FRLOCKS = 0,
VCHANGE_FLAGS_ENF_LOCKING = 1,
VCHANGE_FLAGS_TRUNCATED = 2,
VCHANGE_FLAGS_PAGE_DIRTY = 3,
VCHANGE_FLAGS_IOEXCL_COUNT = 4
} vchange_t;
struct file_lock;
struct xfs_iomap_s;
struct xfs_vattr;
struct attrlist_cursor_kern;
typedef int (*xfs_vop_open_t)(bhv_desc_t *, struct cred *);
typedef ssize_t (*xfs_vop_read_t)(bhv_desc_t *, uio_t *, int, struct cred *);
typedef ssize_t (*xfs_vop_write_t)(bhv_desc_t *, uio_t *, int, struct cred *);
typedef int (*xfs_vop_ioctl_t)(bhv_desc_t *, struct inode *, struct file *,
int, u_long, void *);
typedef int (*xfs_vop_getattr_t)(bhv_desc_t *, struct xfs_vattr *, int,
struct cred *);
typedef int (*xfs_vop_setattr_t)(bhv_desc_t *, struct xfs_vattr *, int,
struct cred *);
typedef int (*xfs_vop_access_t)(bhv_desc_t *, int, struct cred *);
typedef int (*xfs_vop_lookup_t)(bhv_desc_t *, vname_t *, xfs_vnode_t **,
int, xfs_vnode_t *, struct cred *);
typedef int (*xfs_vop_create_t)(bhv_desc_t *, vname_t *, struct xfs_vattr *,
xfs_vnode_t **, struct cred *);
typedef int (*xfs_vop_remove_t)(bhv_desc_t *, bhv_desc_t *, vname_t *, struct cred *);
typedef int (*xfs_vop_link_t)(bhv_desc_t *, xfs_vnode_t *, vname_t *,
struct cred *);
typedef int (*xfs_vop_rename_t)(bhv_desc_t *, vname_t *, xfs_vnode_t *, vname_t *,
struct cred *);
typedef int (*xfs_vop_mkdir_t)(bhv_desc_t *, vname_t *, struct xfs_vattr *,
xfs_vnode_t **, struct cred *);
typedef int (*xfs_vop_rmdir_t)(bhv_desc_t *, vname_t *, struct cred *);
typedef int (*xfs_vop_readdir_t)(bhv_desc_t *, struct uio *, struct cred *,
int *);
typedef int (*xfs_vop_symlink_t)(bhv_desc_t *, vname_t *, struct xfs_vattr *,
char *, xfs_vnode_t **, struct cred *);
typedef int (*xfs_vop_readlink_t)(bhv_desc_t *, struct uio *, int,
struct cred *);
typedef int (*xfs_vop_fsync_t)(bhv_desc_t *, int, struct cred *,
xfs_off_t, xfs_off_t);
typedef int (*xfs_vop_inactive_t)(bhv_desc_t *, struct cred *);
typedef int (*xfs_vop_fid2_t)(bhv_desc_t *, struct fid *);
typedef int (*xfs_vop_release_t)(bhv_desc_t *);
typedef int (*xfs_vop_rwlock_t)(bhv_desc_t *, vrwlock_t);
typedef void (*xfs_vop_rwunlock_t)(bhv_desc_t *, vrwlock_t);
typedef int (*xfs_vop_frlock_t)(bhv_desc_t *, int, struct file_lock *,int,
xfs_off_t, struct cred *);
typedef int (*xfs_vop_bmap_t)(bhv_desc_t *, xfs_off_t, ssize_t, int,
struct xfs_iomap *, int *);
typedef int (*xfs_vop_reclaim_t)(bhv_desc_t *);
typedef int (*xfs_vop_attr_get_t)(bhv_desc_t *, const char *, char *, int *, int,
struct cred *);
typedef int (*xfs_vop_attr_set_t)(bhv_desc_t *, const char *, char *, int, int,
struct cred *);
typedef int (*xfs_vop_attr_remove_t)(bhv_desc_t *, const char *, int, struct cred *);
typedef int (*xfs_vop_attr_list_t)(bhv_desc_t *, char *, int, int,
struct attrlist_cursor_kern *, struct cred *);
typedef void (*xfs_vop_link_removed_t)(bhv_desc_t *, xfs_vnode_t *, int);
typedef void (*xfs_vop_vnode_change_t)(bhv_desc_t *, vchange_t, __psint_t);
typedef void (*xfs_vop_ptossvp_t)(bhv_desc_t *, xfs_off_t, xfs_off_t, int);
typedef void (*xfs_vop_pflushinvalvp_t)(bhv_desc_t *, xfs_off_t, xfs_off_t, int);
typedef int (*xfs_vop_pflushvp_t)(bhv_desc_t *, xfs_off_t, xfs_off_t,
uint64_t, int);
typedef int (*xfs_vop_iflush_t)(bhv_desc_t *, int);
typedef struct xfs_vnodeops {
bhv_position_t vn_position; /* position within behavior chain */
xfs_vop_open_t vop_open;
xfs_vop_read_t vop_read;
xfs_vop_write_t vop_write;
xfs_vop_ioctl_t vop_ioctl;
xfs_vop_getattr_t vop_getattr;
xfs_vop_setattr_t vop_setattr;
xfs_vop_access_t vop_access;
xfs_vop_lookup_t vop_lookup;
xfs_vop_create_t vop_create;
xfs_vop_remove_t vop_remove;
xfs_vop_link_t vop_link;
xfs_vop_rename_t vop_rename;
xfs_vop_mkdir_t vop_mkdir;
xfs_vop_rmdir_t vop_rmdir;
xfs_vop_readdir_t vop_readdir;
xfs_vop_symlink_t vop_symlink;
xfs_vop_readlink_t vop_readlink;
xfs_vop_fsync_t vop_fsync;
xfs_vop_inactive_t vop_inactive;
xfs_vop_fid2_t vop_fid2;
xfs_vop_rwlock_t vop_rwlock;
xfs_vop_rwunlock_t vop_rwunlock;
xfs_vop_frlock_t vop_frlock;
xfs_vop_bmap_t vop_bmap;
xfs_vop_reclaim_t vop_reclaim;
xfs_vop_attr_get_t vop_attr_get;
xfs_vop_attr_set_t vop_attr_set;
xfs_vop_attr_remove_t vop_attr_remove;
xfs_vop_attr_list_t vop_attr_list;
xfs_vop_link_removed_t vop_link_removed;
xfs_vop_vnode_change_t vop_vnode_change;
xfs_vop_ptossvp_t vop_tosspages;
xfs_vop_pflushinvalvp_t vop_flushinval_pages;
xfs_vop_pflushvp_t vop_flush_pages;
xfs_vop_release_t vop_release;
xfs_vop_iflush_t vop_iflush;
} xfs_vnodeops_t;
/*
* VOP's.
*/
#define _VOP_(op, vp) (*((xfs_vnodeops_t *)(vp)->v_fops)->op)
#define XVOP_READ(vp,uio,ioflags,cr,rv) \
rv = _VOP_(vop_read, vp)((vp)->v_fbhv,uio,ioflags,cr)
#define XVOP_WRITE(vp,file,uio,ioflags,cr,rv) \
rv = _VOP_(vop_write, vp)((vp)->v_fbhv,uio,ioflags,cr)
#define XVOP_BMAP(vp,of,sz,rw,b,n,rv) \
rv = _VOP_(vop_bmap, vp)((vp)->v_fbhv,of,sz,rw,b,n)
#define XVOP_OPEN(vp, cr, rv) \
rv = _VOP_(vop_open, vp)((vp)->v_fbhv, cr)
#define XVOP_GETATTR(vp, vap, f, cr, rv) \
rv = _VOP_(vop_getattr, vp)((vp)->v_fbhv, vap, f, cr)
#define XVOP_SETATTR(vp, vap, f, cr, rv) \
rv = _VOP_(vop_setattr, vp)((vp)->v_fbhv, vap, f, cr)
#define XVOP_ACCESS(vp, accmode, cr, rv) \
rv = _VOP_(vop_access, vp)((vp)->v_fbhv, accmode, cr)
#define XVOP_LOOKUP(vp,d,vpp,f,rdir,cr,rv) \
rv = _VOP_(vop_lookup, vp)((vp)->v_fbhv,d,vpp,f,rdir,cr)
#define XVOP_CREATE(dvp,d,vap,vpp,cr,rv) \
rv = _VOP_(vop_create, dvp)((dvp)->v_fbhv,d,vap,vpp,cr)
#define XVOP_REMOVE(dvp,d,cr,rv) \
rv = _VOP_(vop_remove, dvp)((dvp)->v_fbhv,d,cr)
#define XVOP_LINK(tdvp,fvp,d,cr,rv) \
rv = _VOP_(vop_link, tdvp)((tdvp)->v_fbhv,fvp,d,cr)
#define XVOP_RENAME(fvp,fnm,tdvp,tnm,cr,rv) \
rv = _VOP_(vop_rename, fvp)((fvp)->v_fbhv,fnm,tdvp,tnm,cr)
#define XVOP_MKDIR(dp,d,vap,vpp,cr,rv) \
rv = _VOP_(vop_mkdir, dp)((dp)->v_fbhv,d,vap,vpp,cr)
#define XVOP_RMDIR(dp,d,cr,rv) \
rv = _VOP_(vop_rmdir, dp)((dp)->v_fbhv,d,cr)
#define XVOP_READDIR(vp,uiop,cr,eofp,rv) \
rv = _VOP_(vop_readdir, vp)((vp)->v_fbhv,uiop,cr,eofp)
#define XVOP_SYMLINK(dvp,d,vap,tnm,vpp,cr,rv) \
rv = _VOP_(vop_symlink, dvp) ((dvp)->v_fbhv,d,vap,tnm,vpp,cr)
#define XVOP_READLINK(vp,uiop,fl,cr,rv) \
rv = _VOP_(vop_readlink, vp)((vp)->v_fbhv,uiop,fl,cr)
#define XVOP_FSYNC(vp,f,cr,b,e,rv) \
rv = _VOP_(vop_fsync, vp)((vp)->v_fbhv,f,cr,b,e)
#define XVOP_INACTIVE(vp, cr, rv) \
rv = _VOP_(vop_inactive, vp)((vp)->v_fbhv, cr)
#define XVOP_RELEASE(vp, rv) \
rv = _VOP_(vop_release, vp)((vp)->v_fbhv)
#define XVOP_FID2(vp, fidp, rv) \
rv = _VOP_(vop_fid2, vp)((vp)->v_fbhv, fidp)
#define XVOP_RWLOCK(vp,i) \
(void)_VOP_(vop_rwlock, vp)((vp)->v_fbhv, i)
#define XVOP_RWLOCK_TRY(vp,i) \
_VOP_(vop_rwlock, vp)((vp)->v_fbhv, i)
#define XVOP_RWUNLOCK(vp,i) \
(void)_VOP_(vop_rwunlock, vp)((vp)->v_fbhv, i)
#define XVOP_FRLOCK(vp,c,fl,flags,offset,fr,rv) \
rv = _VOP_(vop_frlock, vp)((vp)->v_fbhv,c,fl,flags,offset,fr)
#define XVOP_RECLAIM(vp, rv) \
rv = _VOP_(vop_reclaim, vp)((vp)->v_fbhv)
#define XVOP_ATTR_GET(vp, name, val, vallenp, fl, cred, rv) \
rv = _VOP_(vop_attr_get, vp)((vp)->v_fbhv,name,val,vallenp,fl,cred)
#define XVOP_ATTR_SET(vp, name, val, vallen, fl, cred, rv) \
rv = _VOP_(vop_attr_set, vp)((vp)->v_fbhv,name,val,vallen,fl,cred)
#define XVOP_ATTR_REMOVE(vp, name, flags, cred, rv) \
rv = _VOP_(vop_attr_remove, vp)((vp)->v_fbhv,name,flags,cred)
#define XVOP_ATTR_LIST(vp, buf, buflen, fl, cursor, cred, rv) \
rv = _VOP_(vop_attr_list, vp)((vp)->v_fbhv,buf,buflen,fl,cursor,cred)
#define XVOP_LINK_REMOVED(vp, dvp, linkzero) \
(void)_VOP_(vop_link_removed, vp)((vp)->v_fbhv, dvp, linkzero)
#define XVOP_VNODE_CHANGE(vp, cmd, val) \
(void)_VOP_(vop_vnode_change, vp)((vp)->v_fbhv,cmd,val)
/*
* These are page cache functions that now go thru VOPs.
* 'last' parameter is unused and left in for IRIX compatibility
*/
#define XVOP_TOSS_PAGES(vp, first, last, fiopt) \
_VOP_(vop_tosspages, vp)((vp)->v_fbhv,first, last, fiopt)
/*
* 'last' parameter is unused and left in for IRIX compatibility
*/
#define XVOP_FLUSHINVAL_PAGES(vp, first, last, fiopt) \
_VOP_(vop_flushinval_pages, vp)((vp)->v_fbhv,first,last,fiopt)
/*
* 'last' parameter is unused and left in for IRIX compatibility
*/
#define XVOP_FLUSH_PAGES(vp, first, last, flags, fiopt, rv) \
rv = _VOP_(vop_flush_pages, vp)((vp)->v_fbhv,first,last,flags,fiopt)
#define XVOP_IOCTL(vp, inode, filp, fl, cmd, arg, rv) \
rv = _VOP_(vop_ioctl, vp)((vp)->v_fbhv,inode,filp,fl,cmd,arg)
#define XVOP_IFLUSH(vp, flags, rv) \
rv = _VOP_(vop_iflush, vp)((vp)->v_fbhv, flags)
/*
* Flags for read/write calls - select values from FreeBSD IO_ flags
* or non-conflicting bits.
*/
#define IO_ISDIRECT IO_DIRECT /* bypass page cache */
#define IO_INVIS 0x02000 /* don't update inode timestamps */
/* #define IO_ISLOCKED 0x04000 don't do inode locking, strictly a CXFS thing */
/*
* Flags for VOP_IFLUSH call
*/
#define FLUSH_SYNC 1 /* wait for flush to complete */
#define FLUSH_INODE 2 /* flush the inode itself */
#define FLUSH_LOG 4 /* force the last log entry for
* this inode out to disk */
/*
* Flush/Invalidate options for VOP_TOSS_PAGES, VOP_FLUSHINVAL_PAGES and
* VOP_FLUSH_PAGES.
*/
#define FI_NONE 0 /* none */
#define FI_REMAPF 1 /* Do a remapf prior to the operation */
#define FI_REMAPF_LOCKED 2 /* Do a remapf prior to the operation.
Prevent VM access to the pages until
the operation completes. */
/*
* Vnode attributes. va_mask indicates those attributes the caller
* wants to set or extract.
*/
typedef struct xfs_vattr {
int va_mask; /* bit-mask of attributes present */
mode_t va_mode; /* file access mode and type */
nlink_t va_nlink; /* number of references to file */
uid_t va_uid; /* owner user id */
gid_t va_gid; /* owner group id */
xfs_ino_t va_nodeid; /* file id */
xfs_off_t va_size; /* file size in bytes */
u_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_int va_gen; /* generation number of file */
xfs_dev_t va_rdev; /* device the special file represents */
__int64_t va_nblocks; /* number of blocks allocated */
u_long va_xflags; /* random extended file flags */
u_long va_extsize; /* file extent size */
u_long va_nextents; /* number of extents in file */
u_long va_anextents; /* number of attr extents in file */
int va_projid; /* project id */
} xfs_vattr_t;
/*
* setattr or getattr attributes
*/
#define XFS_AT_TYPE 0x00000001
#define XFS_AT_MODE 0x00000002
#define XFS_AT_UID 0x00000004
#define XFS_AT_GID 0x00000008
#define XFS_AT_FSID 0x00000010
#define XFS_AT_NODEID 0x00000020
#define XFS_AT_NLINK 0x00000040
#define XFS_AT_SIZE 0x00000080
#define XFS_AT_ATIME 0x00000100
#define XFS_AT_MTIME 0x00000200
#define XFS_AT_CTIME 0x00000400
#define XFS_AT_RDEV 0x00000800
#define XFS_AT_BLKSIZE 0x00001000
#define XFS_AT_NBLOCKS 0x00002000
#define XFS_AT_VCODE 0x00004000
#define XFS_AT_MAC 0x00008000
#define XFS_AT_UPDATIME 0x00010000
#define XFS_AT_UPDMTIME 0x00020000
#define XFS_AT_UPDCTIME 0x00040000
#define XFS_AT_ACL 0x00080000
#define XFS_AT_CAP 0x00100000
#define XFS_AT_INF 0x00200000
#define XFS_AT_XFLAGS 0x00400000
#define XFS_AT_EXTSIZE 0x00800000
#define XFS_AT_NEXTENTS 0x01000000
#define XFS_AT_ANEXTENTS 0x02000000
#define XFS_AT_PROJID 0x04000000
#define XFS_AT_SIZE_NOPERM 0x08000000
#define XFS_AT_GENCOUNT 0x10000000
#define XFS_AT_ALL (XFS_AT_TYPE|XFS_AT_MODE|XFS_AT_UID|XFS_AT_GID|\
XFS_AT_FSID|XFS_AT_NODEID|XFS_AT_NLINK|XFS_AT_SIZE|\
XFS_AT_ATIME|XFS_AT_MTIME|XFS_AT_CTIME|XFS_AT_RDEV|\
XFS_AT_BLKSIZE|XFS_AT_NBLOCKS|XFS_AT_VCODE|XFS_AT_MAC|\
XFS_AT_ACL|XFS_AT_CAP|XFS_AT_INF|XFS_AT_XFLAGS|XFS_AT_EXTSIZE|\
XFS_AT_NEXTENTS|XFS_AT_ANEXTENTS|XFS_AT_PROJID|XFS_AT_GENCOUNT)
#define XFS_AT_STAT (XFS_AT_TYPE|XFS_AT_MODE|XFS_AT_UID|XFS_AT_GID|\
XFS_AT_FSID|XFS_AT_NODEID|XFS_AT_NLINK|XFS_AT_SIZE|\
XFS_AT_ATIME|XFS_AT_MTIME|XFS_AT_CTIME|XFS_AT_RDEV|\
XFS_AT_BLKSIZE|XFS_AT_NBLOCKS|XFS_AT_PROJID)
#define XFS_AT_TIMES (XFS_AT_ATIME|XFS_AT_MTIME|XFS_AT_CTIME)
#define XFS_AT_UPDTIMES (XFS_AT_UPDATIME|XFS_AT_UPDMTIME|XFS_AT_UPDCTIME)
#define XFS_AT_NOSET (XFS_AT_NLINK|XFS_AT_RDEV|XFS_AT_FSID|XFS_AT_NODEID|\
XFS_AT_TYPE|XFS_AT_BLKSIZE|XFS_AT_NBLOCKS|XFS_AT_VCODE|\
XFS_AT_NEXTENTS|XFS_AT_ANEXTENTS|XFS_AT_GENCOUNT)
#ifndef __FreeBSD__
/*
* Modes.
*/
#define VSUID S_ISUID /* set user id on execution */
#define VSGID S_ISGID /* set group id on execution */
#define VSVTX S_ISVTX /* save swapped text even after use */
#define VREAD S_IRUSR /* read, write, execute permissions */
#define VWRITE S_IWUSR
#define VEXEC S_IXUSR
#endif /* __FreeBSD__ */
#define MODEMASK ALLPERMS /* mode bits plus permission bits */
/*
* Check whether mandatory file locking is enabled.
*/
#define MANDLOCK(vp, mode) \
((vp)->v_vnode->v_type == VREG && ((mode) & (S_ISGID|(VEXEC>>3))) == S_ISGID)
extern void vn_init(void);
extern int vn_wait(struct xfs_vnode *);
extern void vn_iowait(struct xfs_vnode *);
extern xfs_vnode_t *vn_initialize(struct xfs_vnode *);
/*
* Acquiring and invalidating vnodes:
*
* if (vn_get(vp, version, 0))
* ...;
* vn_purge(vp, version);
*
* vn_get and vn_purge must be called with vmap_t arguments, sampled
* while a lock that the vnode's VOP_RECLAIM function acquires is
* held, to ensure that the vnode sampled with the lock held isn't
* recycled (VOP_RECLAIMed) or deallocated between the release of the lock
* and the subsequent vn_get or vn_purge.
*/
/*
* vnode_map structures _must_ match vn_epoch and vnode structure sizes.
*/
typedef struct vnode_map {
xfs_vfs_t *v_vfsp;
xfs_ino_t v_ino;
struct vnode *v_vp;
} vmap_t;
#if 1
#define VMAP(vp, vmap) {(vmap).v_vfsp = (vp)->v_vfsp; \
(vmap).v_vp = (vp)->v_vnode; \
(vmap).v_ino = (vp)->v_inode->i_ino;\
vhold((vp)->v_vnode); \
}
#endif
extern void vn_purge(struct xfs_vnode *);
extern xfs_vnode_t *vn_get(struct xfs_vnode *, vmap_t *);
extern int vn_revalidate(struct xfs_vnode *);
static inline int vn_count(struct xfs_vnode *vp)
{
return vp->v_vnode->v_usecount;
}
/*
* Vnode reference counting functions (and macros for compatibility).
*/
extern xfs_vnode_t *vn_hold(struct xfs_vnode *);
extern void vn_rele(struct xfs_vnode *);
#if defined(XFS_VNODE_TRACE)
#define VN_HOLD(vp) \
((void)vref((vp)->v_vnode), \
vn_trace_hold(vp, __FILE__, __LINE__, (inst_t *)__return_address))
#define VN_RELE(vp) \
(vn_trace_rele(vp, __FILE__, __LINE__, (inst_t *)__return_address), \
vrele((vp)->v_vnode))
#else
#define VN_HOLD(vp) vref((vp)->v_vnode)
#define VN_RELE(vp) vrele((vp)->v_vnode)
#endif
/*
* Vname handling macros.
*/
#define VNAME(cnp) ((cnp)->cn_nameptr)
#define VNAMELEN(cnp) ((cnp)->cn_namelen)
#define VNAME_TO_VNODE(dentry) (printf("VNAME_TO_VNODE NI"), (xfs_vnode_t *)0)
/*
* Vnode spinlock manipulation.
*/
#define VN_LOCK(vp) VI_LOCK(vp->v_vnode)
#define VN_UNLOCK(vp, s) VI_UNLOCK(vp->v_vnode)
#define VN_FLAGSET(vp,b) vn_flagset(vp,b)
#define VN_FLAGCLR(vp,b) vn_flagclr(vp,b)
static __inline__ void vn_flagset(struct xfs_vnode *vp, __u32 flag)
{
VN_LOCK(vp);
vp->v_flag |= flag;
VN_UNLOCK(vp, 0);
}
static __inline__ void vn_flagclr(struct xfs_vnode *vp, __u32 flag)
{
VN_LOCK(vp);
vp->v_flag &= ~flag;
VN_UNLOCK(vp, 0);
}
/*
* Update modify/access/change times on the vnode
*/
#define VN_MTIMESET(vp, tvp)
#define VN_ATIMESET(vp, tvp)
#define VN_CTIMESET(vp, tvp)
/*
* Some useful predicates.
*/
#define VN_MAPPED(vp) 0
#define VN_CACHED(vp) 0
#define VN_DIRTY(vp) 0
#define VMODIFY(vp) VN_FLAGSET(vp, VMODIFIED)
#define VUNMODIFY(vp) VN_FLAGCLR(vp, VMODIFIED)
/*
* Flags to VOP_SETATTR/VOP_GETATTR.
*/
#define ATTR_UTIME 0x01 /* non-default utime(2) request */
#define ATTR_DMI 0x08 /* invocation from a DMI function */
#define ATTR_LAZY 0x80 /* set/get attributes lazily */
#define ATTR_NONBLOCK 0x100 /* return EAGAIN if operation would block */
#define ATTR_NOLOCK 0x200 /* Don't grab any conflicting locks */
#define ATTR_NOSIZETOK 0x400 /* Don't get the SIZE token */
/*
* Flags to VOP_FSYNC and VOP_RECLAIM.
*/
#define FSYNC_NOWAIT 0 /* asynchronous flush */
#define FSYNC_WAIT 0x1 /* synchronous fsync or forced reclaim */
#define FSYNC_INVAL 0x2 /* flush and invalidate cached data */
#define FSYNC_DATA 0x4 /* synchronous fsync of data only */
static inline struct xfs_vnode *vn_grab(struct xfs_vnode *vp)
{
printf("vn_grab NI\n");
// struct inode *inode = igrab(vn_to_inode(vp));
// return inode ? vn_from_inode(inode) : NULL;
return NULL;
}
static inline void vn_atime_to_bstime(struct xfs_vnode *vp, xfs_bstime_t *bs_atime)
{
printf("%s NI\n", __func__);
// bs_atime->tv_sec = vp->v_inode.i_atime.tv_sec;
// bs_atime->tv_nsec = vp->v_inode.i_atime.tv_nsec;
}
static inline void vn_atime_to_timespec(struct xfs_vnode *vp, struct timespec *ts)
{
// *ts = vp->v_vnode->va_atime;
}
/*
* Tracking vnode activity.
*/
#if defined(XFS_VNODE_TRACE)
#define VNODE_TRACE_SIZE 16 /* number of trace entries */
#define VNODE_KTRACE_ENTRY 1
#define VNODE_KTRACE_EXIT 2
#define VNODE_KTRACE_HOLD 3
#define VNODE_KTRACE_REF 4
#define VNODE_KTRACE_RELE 5
extern void vn_trace_entry(struct xfs_vnode *, char *, inst_t *);
extern void vn_trace_exit(struct xfs_vnode *, char *, inst_t *);
extern void vn_trace_hold(struct xfs_vnode *, char *, int, inst_t *);
extern void vn_trace_ref(struct xfs_vnode *, char *, int, inst_t *);
extern void vn_trace_rele(struct xfs_vnode *, char *, int, inst_t *);
#define VN_TRACE(vp) \
vn_trace_ref(vp, __FILE__, __LINE__, (inst_t *)__return_address)
#else
#define vn_trace_entry(a,b,c)
#define vn_trace_exit(a,b,c)
#define vn_trace_hold(a,b,c,d)
#define vn_trace_ref(a,b,c,d)
#define vn_trace_rele(a,b,c,d)
#define VN_TRACE(vp)
#endif
#endif /* __XFS_VNODE_H__ */

File diff suppressed because it is too large Load Diff

View File

@ -1,23 +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
*/
#ifndef __XFS_H__
#define __XFS_H__
#include <xfs_freebsd.h>
#endif /* __XFS_H__ */

View File

@ -1,928 +0,0 @@
/*
* Copyright (c) 2001-2002,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"
#include "xfs_fs.h"
#include "xfs_types.h"
#include "xfs_bit.h"
#include "xfs_inum.h"
#include "xfs_ag.h"
#include "xfs_dir.h"
#include "xfs_dir2.h"
#include "xfs_bmap_btree.h"
#include "xfs_alloc_btree.h"
#include "xfs_ialloc_btree.h"
#include "xfs_dir_sf.h"
#include "xfs_dir2_sf.h"
#include "xfs_attr_sf.h"
#include "xfs_dinode.h"
#include "xfs_inode.h"
#include "xfs_btree.h"
#include "xfs_acl.h"
#include "xfs_mac.h"
#include "xfs_attr.h"
#include <linux/capability.h>
#include <linux/posix_acl_xattr.h>
STATIC int xfs_acl_setmode(xfs_vnode_t *, xfs_acl_t *, int *);
STATIC void xfs_acl_filter_mode(mode_t, xfs_acl_t *);
STATIC void xfs_acl_get_endian(xfs_acl_t *);
STATIC int xfs_acl_access(uid_t, gid_t, xfs_acl_t *, mode_t, cred_t *);
STATIC int xfs_acl_invalid(xfs_acl_t *);
STATIC void xfs_acl_sync_mode(mode_t, xfs_acl_t *);
STATIC void xfs_acl_get_attr(xfs_vnode_t *, xfs_acl_t *, int, int, int *);
STATIC void xfs_acl_set_attr(xfs_vnode_t *, xfs_acl_t *, int, int *);
STATIC int xfs_acl_allow_set(xfs_vnode_t *, int);
kmem_zone_t *xfs_acl_zone;
/*
* Test for existence of access ACL attribute as efficiently as possible.
*/
int
xfs_acl_vhasacl_access(
xfs_vnode_t *vp)
{
int error;
xfs_acl_get_attr(vp, NULL, _ACL_TYPE_ACCESS, ATTR_KERNOVAL, &error);
return (error == 0);
}
/*
* Test for existence of default ACL attribute as efficiently as possible.
*/
int
xfs_acl_vhasacl_default(
xfs_vnode_t *vp)
{
int error;
if (!VN_ISDIR(vp))
return 0;
xfs_acl_get_attr(vp, NULL, _ACL_TYPE_DEFAULT, ATTR_KERNOVAL, &error);
return (error == 0);
}
/*
* Convert from extended attribute representation to in-memory for XFS.
*/
STATIC int
posix_acl_xattr_to_xfs(
posix_acl_xattr_header *src,
size_t size,
xfs_acl_t *dest)
{
posix_acl_xattr_entry *src_entry;
xfs_acl_entry_t *dest_entry;
int n;
if (!src || !dest)
return EINVAL;
if (size < sizeof(posix_acl_xattr_header))
return EINVAL;
if (src->a_version != cpu_to_le32(POSIX_ACL_XATTR_VERSION))
return EOPNOTSUPP;
memset(dest, 0, sizeof(xfs_acl_t));
dest->acl_cnt = posix_acl_xattr_count(size);
if (dest->acl_cnt < 0 || dest->acl_cnt > XFS_ACL_MAX_ENTRIES)
return EINVAL;
/*
* acl_set_file(3) may request that we set default ACLs with
* zero length -- defend (gracefully) against that here.
*/
if (!dest->acl_cnt)
return 0;
src_entry = (posix_acl_xattr_entry *)((char *)src + sizeof(*src));
dest_entry = &dest->acl_entry[0];
for (n = 0; n < dest->acl_cnt; n++, src_entry++, dest_entry++) {
dest_entry->ae_perm = le16_to_cpu(src_entry->e_perm);
if (_ACL_PERM_INVALID(dest_entry->ae_perm))
return EINVAL;
dest_entry->ae_tag = le16_to_cpu(src_entry->e_tag);
switch(dest_entry->ae_tag) {
case ACL_USER:
case ACL_GROUP:
dest_entry->ae_id = le32_to_cpu(src_entry->e_id);
break;
case ACL_USER_OBJ:
case ACL_GROUP_OBJ:
case ACL_MASK:
case ACL_OTHER:
dest_entry->ae_id = ACL_UNDEFINED_ID;
break;
default:
return EINVAL;
}
}
if (xfs_acl_invalid(dest))
return EINVAL;
return 0;
}
/*
* Comparison function called from xfs_sort().
* Primary key is ae_tag, secondary key is ae_id.
*/
STATIC int
xfs_acl_entry_compare(
const void *va,
const void *vb)
{
xfs_acl_entry_t *a = (xfs_acl_entry_t *)va,
*b = (xfs_acl_entry_t *)vb;
if (a->ae_tag == b->ae_tag)
return (a->ae_id - b->ae_id);
return (a->ae_tag - b->ae_tag);
}
/*
* Convert from in-memory XFS to extended attribute representation.
*/
STATIC int
posix_acl_xfs_to_xattr(
xfs_acl_t *src,
posix_acl_xattr_header *dest,
size_t size)
{
int n;
size_t new_size = posix_acl_xattr_size(src->acl_cnt);
posix_acl_xattr_entry *dest_entry;
xfs_acl_entry_t *src_entry;
if (size < new_size)
return -ERANGE;
/* Need to sort src XFS ACL by <ae_tag,ae_id> */
xfs_sort(src->acl_entry, src->acl_cnt, sizeof(src->acl_entry[0]),
xfs_acl_entry_compare);
dest->a_version = cpu_to_le32(POSIX_ACL_XATTR_VERSION);
dest_entry = &dest->a_entries[0];
src_entry = &src->acl_entry[0];
for (n = 0; n < src->acl_cnt; n++, dest_entry++, src_entry++) {
dest_entry->e_perm = cpu_to_le16(src_entry->ae_perm);
if (_ACL_PERM_INVALID(src_entry->ae_perm))
return -EINVAL;
dest_entry->e_tag = cpu_to_le16(src_entry->ae_tag);
switch (src_entry->ae_tag) {
case ACL_USER:
case ACL_GROUP:
dest_entry->e_id = cpu_to_le32(src_entry->ae_id);
break;
case ACL_USER_OBJ:
case ACL_GROUP_OBJ:
case ACL_MASK:
case ACL_OTHER:
dest_entry->e_id = cpu_to_le32(ACL_UNDEFINED_ID);
break;
default:
return -EINVAL;
}
}
return new_size;
}
int
xfs_acl_vget(
xfs_vnode_t *vp,
void *acl,
size_t size,
int kind)
{
int error;
xfs_acl_t *xfs_acl = NULL;
posix_acl_xattr_header *ext_acl = acl;
int flags = 0;
VN_HOLD(vp);
if(size) {
if (!(_ACL_ALLOC(xfs_acl))) {
error = ENOMEM;
goto out;
}
memset(xfs_acl, 0, sizeof(xfs_acl_t));
} else
flags = ATTR_KERNOVAL;
xfs_acl_get_attr(vp, xfs_acl, kind, flags, &error);
if (error)
goto out;
if (!size) {
error = -posix_acl_xattr_size(XFS_ACL_MAX_ENTRIES);
} else {
if (xfs_acl_invalid(xfs_acl)) {
error = EINVAL;
goto out;
}
if (kind == _ACL_TYPE_ACCESS) {
xfs_vattr_t va;
va.va_mask = XFS_AT_MODE;
XVOP_GETATTR(vp, &va, 0, sys_cred, error);
if (error)
goto out;
xfs_acl_sync_mode(va.va_mode, xfs_acl);
}
error = -posix_acl_xfs_to_xattr(xfs_acl, ext_acl, size);
}
out:
VN_RELE(vp);
if(xfs_acl)
_ACL_FREE(xfs_acl);
return -error;
}
int
xfs_acl_vremove(
xfs_vnode_t *vp,
int kind)
{
int error;
VN_HOLD(vp);
error = xfs_acl_allow_set(vp, kind);
if (!error) {
XVOP_ATTR_REMOVE(vp, kind == _ACL_TYPE_DEFAULT?
SGI_ACL_DEFAULT: SGI_ACL_FILE,
ATTR_ROOT, sys_cred, error);
if (error == ENOATTR)
error = 0; /* 'scool */
}
VN_RELE(vp);
return -error;
}
int
xfs_acl_vset(
xfs_vnode_t *vp,
void *acl,
size_t size,
int kind)
{
posix_acl_xattr_header *ext_acl = acl;
xfs_acl_t *xfs_acl;
int error;
int basicperms = 0; /* more than std unix perms? */
if (!acl)
return -EINVAL;
if (!(_ACL_ALLOC(xfs_acl)))
return -ENOMEM;
error = posix_acl_xattr_to_xfs(ext_acl, size, xfs_acl);
if (error) {
_ACL_FREE(xfs_acl);
return -error;
}
if (!xfs_acl->acl_cnt) {
_ACL_FREE(xfs_acl);
return 0;
}
VN_HOLD(vp);
error = xfs_acl_allow_set(vp, kind);
if (error)
goto out;
/* Incoming ACL exists, set file mode based on its value */
if (kind == _ACL_TYPE_ACCESS)
xfs_acl_setmode(vp, xfs_acl, &basicperms);
/*
* If we have more than std unix permissions, set up the actual attr.
* Otherwise, delete any existing attr. This prevents us from
* having actual attrs for permissions that can be stored in the
* standard permission bits.
*/
if (!basicperms) {
xfs_acl_set_attr(vp, xfs_acl, kind, &error);
} else {
xfs_acl_vremove(vp, _ACL_TYPE_ACCESS);
}
out:
VN_RELE(vp);
_ACL_FREE(xfs_acl);
return -error;
}
int
xfs_acl_iaccess(
xfs_inode_t *ip,
mode_t mode,
cred_t *cr)
{
xfs_acl_t *acl;
int rval;
if (!(_ACL_ALLOC(acl)))
return -1;
/* If the file has no ACL return -1. */
rval = sizeof(xfs_acl_t);
if (xfs_attr_fetch(ip, SGI_ACL_FILE, SGI_ACL_FILE_SIZE,
(char *)acl, &rval, ATTR_ROOT | ATTR_KERNACCESS, cr)) {
_ACL_FREE(acl);
return -1;
}
xfs_acl_get_endian(acl);
/* If the file has an empty ACL return -1. */
if (acl->acl_cnt == XFS_ACL_NOT_PRESENT) {
_ACL_FREE(acl);
return -1;
}
/* Synchronize ACL with mode bits */
xfs_acl_sync_mode(ip->i_d.di_mode, acl);
rval = xfs_acl_access(ip->i_d.di_uid, ip->i_d.di_gid, acl, mode, cr);
_ACL_FREE(acl);
return rval;
}
STATIC int
xfs_acl_allow_set(
xfs_vnode_t *vp,
int kind)
{
xfs_vattr_t va;
int error;
if (vp->v_inode.i_flags & (S_IMMUTABLE|S_APPEND))
return EPERM;
if (kind == _ACL_TYPE_DEFAULT && !VN_ISDIR(vp))
return ENOTDIR;
if (vp->v_vfsp->vfs_flag & VFS_RDONLY)
return EROFS;
va.va_mask = XFS_AT_UID;
XVOP_GETATTR(vp, &va, 0, NULL, error);
if (error)
return error;
if (va.va_uid != current->fsuid && !capable(CAP_FOWNER))
return EPERM;
return error;
}
/*
* The access control process to determine the access permission:
* if uid == file owner id, use the file owner bits.
* if gid == file owner group id, use the file group bits.
* scan ACL for a matching user or group, and use matched entry
* permission. Use total permissions of all matching group entries,
* until all acl entries are exhausted. The final permission produced
* by matching acl entry or entries needs to be & with group permission.
* if not owner, owning group, or matching entry in ACL, use file
* other bits.
*/
STATIC int
xfs_acl_capability_check(
mode_t mode,
cred_t *cr)
{
if ((mode & ACL_READ) && !capable_cred(cr, CAP_DAC_READ_SEARCH))
return EACCES;
if ((mode & ACL_WRITE) && !capable_cred(cr, CAP_DAC_OVERRIDE))
return EACCES;
if ((mode & ACL_EXECUTE) && !capable_cred(cr, CAP_DAC_OVERRIDE))
return EACCES;
return 0;
}
/*
* Note: cr is only used here for the capability check if the ACL test fails.
* It is not used to find out the credentials uid or groups etc, as was
* done in IRIX. It is assumed that the uid and groups for the current
* thread are taken from "current" instead of the cr parameter.
*/
STATIC int
xfs_acl_access(
uid_t fuid,
gid_t fgid,
xfs_acl_t *fap,
mode_t md,
cred_t *cr)
{
xfs_acl_entry_t matched;
int i, allows;
int maskallows = -1; /* true, but not 1, either */
int seen_userobj = 0;
matched.ae_tag = 0; /* Invalid type */
matched.ae_perm = 0;
md >>= 6; /* Normalize the bits for comparison */
for (i = 0; i < fap->acl_cnt; i++) {
/*
* Break out if we've got a user_obj entry or
* a user entry and the mask (and have processed USER_OBJ)
*/
if (matched.ae_tag == ACL_USER_OBJ)
break;
if (matched.ae_tag == ACL_USER) {
if (maskallows != -1 && seen_userobj)
break;
if (fap->acl_entry[i].ae_tag != ACL_MASK &&
fap->acl_entry[i].ae_tag != ACL_USER_OBJ)
continue;
}
/* True if this entry allows the requested access */
allows = ((fap->acl_entry[i].ae_perm & md) == md);
switch (fap->acl_entry[i].ae_tag) {
case ACL_USER_OBJ:
seen_userobj = 1;
if (fuid != current->fsuid)
continue;
matched.ae_tag = ACL_USER_OBJ;
matched.ae_perm = allows;
break;
case ACL_USER:
if (fap->acl_entry[i].ae_id != current->fsuid)
continue;
matched.ae_tag = ACL_USER;
matched.ae_perm = allows;
break;
case ACL_GROUP_OBJ:
if ((matched.ae_tag == ACL_GROUP_OBJ ||
matched.ae_tag == ACL_GROUP) && !allows)
continue;
if (!in_group_p(fgid))
continue;
matched.ae_tag = ACL_GROUP_OBJ;
matched.ae_perm = allows;
break;
case ACL_GROUP:
if ((matched.ae_tag == ACL_GROUP_OBJ ||
matched.ae_tag == ACL_GROUP) && !allows)
continue;
if (!in_group_p(fap->acl_entry[i].ae_id))
continue;
matched.ae_tag = ACL_GROUP;
matched.ae_perm = allows;
break;
case ACL_MASK:
maskallows = allows;
break;
case ACL_OTHER:
if (matched.ae_tag != 0)
continue;
matched.ae_tag = ACL_OTHER;
matched.ae_perm = allows;
break;
}
}
/*
* First possibility is that no matched entry allows access.
* The capability to override DAC may exist, so check for it.
*/
switch (matched.ae_tag) {
case ACL_OTHER:
case ACL_USER_OBJ:
if (matched.ae_perm)
return 0;
break;
case ACL_USER:
case ACL_GROUP_OBJ:
case ACL_GROUP:
if (maskallows && matched.ae_perm)
return 0;
break;
case 0:
break;
}
return xfs_acl_capability_check(md, cr);
}
/*
* ACL validity checker.
* This acl validation routine checks each ACL entry read in makes sense.
*/
STATIC int
xfs_acl_invalid(
xfs_acl_t *aclp)
{
xfs_acl_entry_t *entry, *e;
int user = 0, group = 0, other = 0, mask = 0;
int mask_required = 0;
int i, j;
if (!aclp)
goto acl_invalid;
if (aclp->acl_cnt > XFS_ACL_MAX_ENTRIES)
goto acl_invalid;
for (i = 0; i < aclp->acl_cnt; i++) {
entry = &aclp->acl_entry[i];
switch (entry->ae_tag) {
case ACL_USER_OBJ:
if (user++)
goto acl_invalid;
break;
case ACL_GROUP_OBJ:
if (group++)
goto acl_invalid;
break;
case ACL_OTHER:
if (other++)
goto acl_invalid;
break;
case ACL_USER:
case ACL_GROUP:
for (j = i + 1; j < aclp->acl_cnt; j++) {
e = &aclp->acl_entry[j];
if (e->ae_id == entry->ae_id &&
e->ae_tag == entry->ae_tag)
goto acl_invalid;
}
mask_required++;
break;
case ACL_MASK:
if (mask++)
goto acl_invalid;
break;
default:
goto acl_invalid;
}
}
if (!user || !group || !other || (mask_required && !mask))
goto acl_invalid;
else
return 0;
acl_invalid:
return EINVAL;
}
/*
* Do ACL endian conversion.
*/
STATIC void
xfs_acl_get_endian(
xfs_acl_t *aclp)
{
xfs_acl_entry_t *ace, *end;
INT_SET(aclp->acl_cnt, ARCH_CONVERT, aclp->acl_cnt);
end = &aclp->acl_entry[0]+aclp->acl_cnt;
for (ace = &aclp->acl_entry[0]; ace < end; ace++) {
INT_SET(ace->ae_tag, ARCH_CONVERT, ace->ae_tag);
INT_SET(ace->ae_id, ARCH_CONVERT, ace->ae_id);
INT_SET(ace->ae_perm, ARCH_CONVERT, ace->ae_perm);
}
}
/*
* Get the ACL from the EA and do endian conversion.
*/
STATIC void
xfs_acl_get_attr(
xfs_vnode_t *vp,
xfs_acl_t *aclp,
int kind,
int flags,
int *error)
{
int len = sizeof(xfs_acl_t);
ASSERT((flags & ATTR_KERNOVAL) ? (aclp == NULL) : 1);
flags |= ATTR_ROOT;
XVOP_ATTR_GET(vp,
kind == _ACL_TYPE_ACCESS ? SGI_ACL_FILE : SGI_ACL_DEFAULT,
(char *)aclp, &len, flags, sys_cred, *error);
if (*error || (flags & ATTR_KERNOVAL))
return;
xfs_acl_get_endian(aclp);
}
/*
* Set the EA with the ACL and do endian conversion.
*/
STATIC void
xfs_acl_set_attr(
xfs_vnode_t *vp,
xfs_acl_t *aclp,
int kind,
int *error)
{
xfs_acl_entry_t *ace, *newace, *end;
xfs_acl_t *newacl;
int len;
if (!(_ACL_ALLOC(newacl))) {
*error = ENOMEM;
return;
}
len = sizeof(xfs_acl_t) -
(sizeof(xfs_acl_entry_t) * (XFS_ACL_MAX_ENTRIES - aclp->acl_cnt));
end = &aclp->acl_entry[0]+aclp->acl_cnt;
for (ace = &aclp->acl_entry[0], newace = &newacl->acl_entry[0];
ace < end;
ace++, newace++) {
INT_SET(newace->ae_tag, ARCH_CONVERT, ace->ae_tag);
INT_SET(newace->ae_id, ARCH_CONVERT, ace->ae_id);
INT_SET(newace->ae_perm, ARCH_CONVERT, ace->ae_perm);
}
INT_SET(newacl->acl_cnt, ARCH_CONVERT, aclp->acl_cnt);
XVOP_ATTR_SET(vp,
kind == _ACL_TYPE_ACCESS ? SGI_ACL_FILE: SGI_ACL_DEFAULT,
(char *)newacl, len, ATTR_ROOT, sys_cred, *error);
_ACL_FREE(newacl);
}
int
xfs_acl_vtoacl(
xfs_vnode_t *vp,
xfs_acl_t *access_acl,
xfs_acl_t *default_acl)
{
xfs_vattr_t va;
int error = 0;
if (access_acl) {
/*
* Get the Access ACL and the mode. If either cannot
* be obtained for some reason, invalidate the access ACL.
*/
xfs_acl_get_attr(vp, access_acl, _ACL_TYPE_ACCESS, 0, &error);
if (!error) {
/* Got the ACL, need the mode... */
va.va_mask = XFS_AT_MODE;
XVOP_GETATTR(vp, &va, 0, sys_cred, error);
}
if (error)
access_acl->acl_cnt = XFS_ACL_NOT_PRESENT;
else /* We have a good ACL and the file mode, synchronize. */
xfs_acl_sync_mode(va.va_mode, access_acl);
}
if (default_acl) {
xfs_acl_get_attr(vp, default_acl, _ACL_TYPE_DEFAULT, 0, &error);
if (error)
default_acl->acl_cnt = XFS_ACL_NOT_PRESENT;
}
return error;
}
/*
* This function retrieves the parent directory's acl, processes it
* and lets the child inherit the acl(s) that it should.
*/
int
xfs_acl_inherit(
xfs_vnode_t *vp,
xfs_vattr_t *vap,
xfs_acl_t *pdaclp)
{
xfs_acl_t *cacl;
int error = 0;
int basicperms = 0;
/*
* If the parent does not have a default ACL, or it's an
* invalid ACL, we're done.
*/
if (!vp)
return 0;
if (!pdaclp || xfs_acl_invalid(pdaclp))
return 0;
/*
* Copy the default ACL of the containing directory to
* the access ACL of the new file and use the mode that
* was passed in to set up the correct initial values for
* the u::,g::[m::], and o:: entries. This is what makes
* umask() "work" with ACL's.
*/
if (!(_ACL_ALLOC(cacl)))
return ENOMEM;
memcpy(cacl, pdaclp, sizeof(xfs_acl_t));
xfs_acl_filter_mode(vap->va_mode, cacl);
xfs_acl_setmode(vp, cacl, &basicperms);
/*
* Set the Default and Access ACL on the file. The mode is already
* set on the file, so we don't need to worry about that.
*
* If the new file is a directory, its default ACL is a copy of
* the containing directory's default ACL.
*/
if (VN_ISDIR(vp))
xfs_acl_set_attr(vp, pdaclp, _ACL_TYPE_DEFAULT, &error);
if (!error && !basicperms)
xfs_acl_set_attr(vp, cacl, _ACL_TYPE_ACCESS, &error);
_ACL_FREE(cacl);
return error;
}
/*
* Set up the correct mode on the file based on the supplied ACL. This
* makes sure that the mode on the file reflects the state of the
* u::,g::[m::], and o:: entries in the ACL. Since the mode is where
* the ACL is going to get the permissions for these entries, we must
* synchronize the mode whenever we set the ACL on a file.
*/
STATIC int
xfs_acl_setmode(
xfs_vnode_t *vp,
xfs_acl_t *acl,
int *basicperms)
{
xfs_vattr_t va;
xfs_acl_entry_t *ap;
xfs_acl_entry_t *gap = NULL;
int i, error, nomask = 1;
*basicperms = 1;
if (acl->acl_cnt == XFS_ACL_NOT_PRESENT)
return 0;
/*
* Copy the u::, g::, o::, and m:: bits from the ACL into the
* mode. The m:: bits take precedence over the g:: bits.
*/
va.va_mask = XFS_AT_MODE;
XVOP_GETATTR(vp, &va, 0, sys_cred, error);
if (error)
return error;
va.va_mask = XFS_AT_MODE;
va.va_mode &= ~(S_IRWXU|S_IRWXG|S_IRWXO);
ap = acl->acl_entry;
for (i = 0; i < acl->acl_cnt; ++i) {
switch (ap->ae_tag) {
case ACL_USER_OBJ:
va.va_mode |= ap->ae_perm << 6;
break;
case ACL_GROUP_OBJ:
gap = ap;
break;
case ACL_MASK: /* more than just standard modes */
nomask = 0;
va.va_mode |= ap->ae_perm << 3;
*basicperms = 0;
break;
case ACL_OTHER:
va.va_mode |= ap->ae_perm;
break;
default: /* more than just standard modes */
*basicperms = 0;
break;
}
ap++;
}
/* Set the group bits from ACL_GROUP_OBJ if there's no ACL_MASK */
if (gap && nomask)
va.va_mode |= gap->ae_perm << 3;
XVOP_SETATTR(vp, &va, 0, sys_cred, error);
return error;
}
/*
* The permissions for the special ACL entries (u::, g::[m::], o::) are
* actually stored in the file mode (if there is both a group and a mask,
* the group is stored in the ACL entry and the mask is stored on the file).
* This allows the mode to remain automatically in sync with the ACL without
* the need for a call-back to the ACL system at every point where the mode
* could change. This function takes the permissions from the specified mode
* and places it in the supplied ACL.
*
* This implementation draws its validity from the fact that, when the ACL
* was assigned, the mode was copied from the ACL.
* If the mode did not change, therefore, the mode remains exactly what was
* taken from the special ACL entries at assignment.
* If a subsequent chmod() was done, the POSIX spec says that the change in
* mode must cause an update to the ACL seen at user level and used for
* access checks. Before and after a mode change, therefore, the file mode
* most accurately reflects what the special ACL entries should permit/deny.
*
* CAVEAT: If someone sets the SGI_ACL_FILE attribute directly,
* the existing mode bits will override whatever is in the
* ACL. Similarly, if there is a pre-existing ACL that was
* never in sync with its mode (owing to a bug in 6.5 and
* before), it will now magically (or mystically) be
* synchronized. This could cause slight astonishment, but
* it is better than inconsistent permissions.
*
* The supplied ACL is a template that may contain any combination
* of special entries. These are treated as place holders when we fill
* out the ACL. This routine does not add or remove special entries, it
* simply unites each special entry with its associated set of permissions.
*/
STATIC void
xfs_acl_sync_mode(
mode_t mode,
xfs_acl_t *acl)
{
int i, nomask = 1;
xfs_acl_entry_t *ap;
xfs_acl_entry_t *gap = NULL;
/*
* Set ACL entries. POSIX1003.1eD16 requires that the MASK
* be set instead of the GROUP entry, if there is a MASK.
*/
for (ap = acl->acl_entry, i = 0; i < acl->acl_cnt; ap++, i++) {
switch (ap->ae_tag) {
case ACL_USER_OBJ:
ap->ae_perm = (mode >> 6) & 0x7;
break;
case ACL_GROUP_OBJ:
gap = ap;
break;
case ACL_MASK:
nomask = 0;
ap->ae_perm = (mode >> 3) & 0x7;
break;
case ACL_OTHER:
ap->ae_perm = mode & 0x7;
break;
default:
break;
}
}
/* Set the ACL_GROUP_OBJ if there's no ACL_MASK */
if (gap && nomask)
gap->ae_perm = (mode >> 3) & 0x7;
}
/*
* When inheriting an Access ACL from a directory Default ACL,
* the ACL bits are set to the intersection of the ACL default
* permission bits and the file permission bits in mode. If there
* are no permission bits on the file then we must not give them
* the ACL. This is what what makes umask() work with ACLs.
*/
STATIC void
xfs_acl_filter_mode(
mode_t mode,
xfs_acl_t *acl)
{
int i, nomask = 1;
xfs_acl_entry_t *ap;
xfs_acl_entry_t *gap = NULL;
/*
* Set ACL entries. POSIX1003.1eD16 requires that the MASK
* be merged with GROUP entry, if there is a MASK.
*/
for (ap = acl->acl_entry, i = 0; i < acl->acl_cnt; ap++, i++) {
switch (ap->ae_tag) {
case ACL_USER_OBJ:
ap->ae_perm &= (mode >> 6) & 0x7;
break;
case ACL_GROUP_OBJ:
gap = ap;
break;
case ACL_MASK:
nomask = 0;
ap->ae_perm &= (mode >> 3) & 0x7;
break;
case ACL_OTHER:
ap->ae_perm &= mode & 0x7;
break;
default:
break;
}
}
/* Set the ACL_GROUP_OBJ if there's no ACL_MASK */
if (gap && nomask)
gap->ae_perm &= (mode >> 3) & 0x7;
}

View File

@ -1,102 +0,0 @@
/*
* Copyright (c) 2001-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
*/
#ifndef __XFS_ACL_H__
#define __XFS_ACL_H__
/*
* Access Control Lists
*/
typedef __uint16_t xfs_acl_perm_t;
typedef __int32_t xfs_acl_type_t;
typedef __int32_t xfs_acl_tag_t;
typedef __int32_t xfs_acl_id_t;
#define XFS_ACL_MAX_ENTRIES 25
#define XFS_ACL_NOT_PRESENT (-1)
typedef struct xfs_acl_entry {
xfs_acl_tag_t ae_tag;
xfs_acl_id_t ae_id;
xfs_acl_perm_t ae_perm;
} xfs_acl_entry_t;
typedef struct xfs_acl {
__int32_t acl_cnt;
xfs_acl_entry_t acl_entry[XFS_ACL_MAX_ENTRIES];
} xfs_acl_t;
/* On-disk XFS extended attribute names */
#define SGI_ACL_FILE "SGI_ACL_FILE"
#define SGI_ACL_DEFAULT "SGI_ACL_DEFAULT"
#define SGI_ACL_FILE_SIZE (sizeof(SGI_ACL_FILE)-1)
#define SGI_ACL_DEFAULT_SIZE (sizeof(SGI_ACL_DEFAULT)-1)
#ifdef CONFIG_XFS_POSIX_ACL
struct vattr;
struct vnode;
struct xfs_inode;
extern struct kmem_zone *xfs_acl_zone;
#define xfs_acl_zone_init(zone, name) \
(zone) = kmem_zone_init(sizeof(xfs_acl_t), (name))
#define xfs_acl_zone_destroy(zone) kmem_zone_destroy(zone)
extern int xfs_acl_inherit(struct vnode *, struct vattr *, xfs_acl_t *);
extern int xfs_acl_iaccess(struct xfs_inode *, mode_t, cred_t *);
extern int xfs_acl_vtoacl(struct vnode *, xfs_acl_t *, xfs_acl_t *);
extern int xfs_acl_vhasacl_access(struct vnode *);
extern int xfs_acl_vhasacl_default(struct vnode *);
extern int xfs_acl_vset(struct vnode *, void *, size_t, int);
extern int xfs_acl_vget(struct vnode *, void *, size_t, int);
extern int xfs_acl_vremove(struct vnode *vp, int);
#define _ACL_TYPE_ACCESS 1
#define _ACL_TYPE_DEFAULT 2
#define _ACL_PERM_INVALID(perm) ((perm) & ~(ACL_READ|ACL_WRITE|ACL_EXECUTE))
#define _ACL_INHERIT(c,v,d) (xfs_acl_inherit(c,v,d))
#define _ACL_GET_ACCESS(pv,pa) (xfs_acl_vtoacl(pv,pa,NULL) == 0)
#define _ACL_GET_DEFAULT(pv,pd) (xfs_acl_vtoacl(pv,NULL,pd) == 0)
#define _ACL_ACCESS_EXISTS xfs_acl_vhasacl_access
#define _ACL_DEFAULT_EXISTS xfs_acl_vhasacl_default
#define _ACL_XFS_IACCESS(i,m,c) (XFS_IFORK_Q(i) ? xfs_acl_iaccess(i,m,c) : -1)
#define _ACL_ALLOC(a) ((a) = kmem_zone_alloc(xfs_acl_zone, KM_SLEEP))
#define _ACL_FREE(a) ((a)? kmem_zone_free(xfs_acl_zone, (a)):(void)0)
#else
#define xfs_acl_zone_init(zone,name)
#define xfs_acl_zone_destroy(zone)
#define xfs_acl_vset(v,p,sz,t) (-EOPNOTSUPP)
#define xfs_acl_vget(v,p,sz,t) (-EOPNOTSUPP)
#define xfs_acl_vremove(v,t) (-EOPNOTSUPP)
#define xfs_acl_vhasacl_access(v) (0)
#define xfs_acl_vhasacl_default(v) (0)
#define _ACL_ALLOC(a) (1) /* successfully allocate nothing */
#define _ACL_FREE(a) ((void)0)
#define _ACL_INHERIT(c,v,d) (0)
#define _ACL_GET_ACCESS(pv,pa) (0)
#define _ACL_GET_DEFAULT(pv,pd) (0)
#define _ACL_ACCESS_EXISTS (NULL)
#define _ACL_DEFAULT_EXISTS (NULL)
#define _ACL_XFS_IACCESS(i,m,c) (-1)
#endif
#endif /* __XFS_ACL_H__ */

View File

@ -1,231 +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
*/
#ifndef __XFS_AG_H__
#define __XFS_AG_H__
/*
* Allocation group header
* This is divided into three structures, placed in sequential 512-byte
* buffers after a copy of the superblock (also in a 512-byte buffer).
*/
struct xfs_buf;
struct xfs_mount;
struct xfs_trans;
#define XFS_AGF_MAGIC 0x58414746 /* 'XAGF' */
#define XFS_AGI_MAGIC 0x58414749 /* 'XAGI' */
#define XFS_AGF_VERSION 1
#define XFS_AGI_VERSION 1
#define XFS_AGF_GOOD_VERSION(v) ((v) == XFS_AGF_VERSION)
#define XFS_AGI_GOOD_VERSION(v) ((v) == XFS_AGI_VERSION)
/*
* Btree number 0 is bno, 1 is cnt. This value gives the size of the
* arrays below.
*/
#define XFS_BTNUM_AGF ((int)XFS_BTNUM_CNTi + 1)
/*
* The second word of agf_levels in the first a.g. overlaps the EFS
* superblock's magic number. Since the magic numbers valid for EFS
* are > 64k, our value cannot be confused for an EFS superblock's.
*/
typedef struct xfs_agf {
/*
* Common allocation group header information
*/
__be32 agf_magicnum; /* magic number == XFS_AGF_MAGIC */
__be32 agf_versionnum; /* header version == XFS_AGF_VERSION */
__be32 agf_seqno; /* sequence # starting from 0 */
__be32 agf_length; /* size in blocks of a.g. */
/*
* Freespace information
*/
__be32 agf_roots[XFS_BTNUM_AGF]; /* root blocks */
__be32 agf_spare0; /* spare field */
__be32 agf_levels[XFS_BTNUM_AGF]; /* btree levels */
__be32 agf_spare1; /* spare field */
__be32 agf_flfirst; /* first freelist block's index */
__be32 agf_fllast; /* last freelist block's index */
__be32 agf_flcount; /* count of blocks in freelist */
__be32 agf_freeblks; /* total free blocks */
__be32 agf_longest; /* longest free space */
} xfs_agf_t;
#define XFS_AGF_MAGICNUM 0x00000001
#define XFS_AGF_VERSIONNUM 0x00000002
#define XFS_AGF_SEQNO 0x00000004
#define XFS_AGF_LENGTH 0x00000008
#define XFS_AGF_ROOTS 0x00000010
#define XFS_AGF_LEVELS 0x00000020
#define XFS_AGF_FLFIRST 0x00000040
#define XFS_AGF_FLLAST 0x00000080
#define XFS_AGF_FLCOUNT 0x00000100
#define XFS_AGF_FREEBLKS 0x00000200
#define XFS_AGF_LONGEST 0x00000400
#define XFS_AGF_NUM_BITS 11
#define XFS_AGF_ALL_BITS ((1 << XFS_AGF_NUM_BITS) - 1)
/* disk block (xfs_daddr_t) in the AG */
#define XFS_AGF_DADDR(mp) ((xfs_daddr_t)(1 << (mp)->m_sectbb_log))
#define XFS_AGF_BLOCK(mp) XFS_HDR_BLOCK(mp, XFS_AGF_DADDR(mp))
#define XFS_BUF_TO_AGF(bp) ((xfs_agf_t *)XFS_BUF_PTR(bp))
/*
* Size of the unlinked inode hash table in the agi.
*/
#define XFS_AGI_UNLINKED_BUCKETS 64
typedef struct xfs_agi {
/*
* Common allocation group header information
*/
__be32 agi_magicnum; /* magic number == XFS_AGI_MAGIC */
__be32 agi_versionnum; /* header version == XFS_AGI_VERSION */
__be32 agi_seqno; /* sequence # starting from 0 */
__be32 agi_length; /* size in blocks of a.g. */
/*
* Inode information
* Inodes are mapped by interpreting the inode number, so no
* mapping data is needed here.
*/
__be32 agi_count; /* count of allocated inodes */
__be32 agi_root; /* root of inode btree */
__be32 agi_level; /* levels in inode btree */
__be32 agi_freecount; /* number of free inodes */
__be32 agi_newino; /* new inode just allocated */
__be32 agi_dirino; /* last directory inode chunk */
/*
* Hash table of inodes which have been unlinked but are
* still being referenced.
*/
__be32 agi_unlinked[XFS_AGI_UNLINKED_BUCKETS];
} xfs_agi_t;
#define XFS_AGI_MAGICNUM 0x00000001
#define XFS_AGI_VERSIONNUM 0x00000002
#define XFS_AGI_SEQNO 0x00000004
#define XFS_AGI_LENGTH 0x00000008
#define XFS_AGI_COUNT 0x00000010
#define XFS_AGI_ROOT 0x00000020
#define XFS_AGI_LEVEL 0x00000040
#define XFS_AGI_FREECOUNT 0x00000080
#define XFS_AGI_NEWINO 0x00000100
#define XFS_AGI_DIRINO 0x00000200
#define XFS_AGI_UNLINKED 0x00000400
#define XFS_AGI_NUM_BITS 11
#define XFS_AGI_ALL_BITS ((1 << XFS_AGI_NUM_BITS) - 1)
/* disk block (xfs_daddr_t) in the AG */
#define XFS_AGI_DADDR(mp) ((xfs_daddr_t)(2 << (mp)->m_sectbb_log))
#define XFS_AGI_BLOCK(mp) XFS_HDR_BLOCK(mp, XFS_AGI_DADDR(mp))
#define XFS_BUF_TO_AGI(bp) ((xfs_agi_t *)XFS_BUF_PTR(bp))
/*
* The third a.g. block contains the a.g. freelist, an array
* of block pointers to blocks owned by the allocation btree code.
*/
#define XFS_AGFL_DADDR(mp) ((xfs_daddr_t)(3 << (mp)->m_sectbb_log))
#define XFS_AGFL_BLOCK(mp) XFS_HDR_BLOCK(mp, XFS_AGFL_DADDR(mp))
#define XFS_AGFL_SIZE(mp) ((mp)->m_sb.sb_sectsize / sizeof(xfs_agblock_t))
#define XFS_BUF_TO_AGFL(bp) ((xfs_agfl_t *)XFS_BUF_PTR(bp))
typedef struct xfs_agfl {
xfs_agblock_t agfl_bno[1]; /* actually XFS_AGFL_SIZE(mp) */
} xfs_agfl_t;
/*
* Busy block/extent entry. Used in perag to mark blocks that have been freed
* but whose transactions aren't committed to disk yet.
*/
typedef struct xfs_perag_busy {
xfs_agblock_t busy_start;
xfs_extlen_t busy_length;
struct xfs_trans *busy_tp; /* transaction that did the free */
} xfs_perag_busy_t;
/*
* Per-ag incore structure, copies of information in agf and agi,
* to improve the performance of allocation group selection.
*
* pick sizes which fit in allocation buckets well
*/
#if (BITS_PER_LONG == 32)
#define XFS_PAGB_NUM_SLOTS 84
#elif (BITS_PER_LONG == 64)
#define XFS_PAGB_NUM_SLOTS 128
#endif
typedef struct xfs_perag
{
char pagf_init; /* this agf's entry is initialized */
char pagi_init; /* this agi's entry is initialized */
char pagf_metadata; /* the agf is preferred to be metadata */
char pagi_inodeok; /* The agi is ok for inodes */
__uint8_t pagf_levels[XFS_BTNUM_AGF];
/* # of levels in bno & cnt btree */
__uint32_t pagf_flcount; /* count of blocks in freelist */
xfs_extlen_t pagf_freeblks; /* total free blocks */
xfs_extlen_t pagf_longest; /* longest free space */
xfs_agino_t pagi_freecount; /* number of free inodes */
#ifdef __KERNEL__
lock_t pagb_lock; /* lock for pagb_list */
#endif
int pagb_count; /* pagb slots in use */
xfs_perag_busy_t *pagb_list; /* unstable blocks */
} xfs_perag_t;
#define XFS_AG_MAXLEVELS(mp) ((mp)->m_ag_maxlevels)
#define XFS_MIN_FREELIST_RAW(bl,cl,mp) \
(MIN(bl + 1, XFS_AG_MAXLEVELS(mp)) + MIN(cl + 1, XFS_AG_MAXLEVELS(mp)))
#define XFS_MIN_FREELIST(a,mp) \
(XFS_MIN_FREELIST_RAW( \
be32_to_cpu((a)->agf_levels[XFS_BTNUM_BNOi]), \
be32_to_cpu((a)->agf_levels[XFS_BTNUM_CNTi]), mp))
#define XFS_MIN_FREELIST_PAG(pag,mp) \
(XFS_MIN_FREELIST_RAW( \
(uint_t)(pag)->pagf_levels[XFS_BTNUM_BNOi], \
(uint_t)(pag)->pagf_levels[XFS_BTNUM_CNTi], mp))
#define XFS_AGB_TO_FSB(mp,agno,agbno) \
(((xfs_fsblock_t)(agno) << (mp)->m_sb.sb_agblklog) | (agbno))
#define XFS_FSB_TO_AGNO(mp,fsbno) \
((xfs_agnumber_t)((fsbno) >> (mp)->m_sb.sb_agblklog))
#define XFS_FSB_TO_AGBNO(mp,fsbno) \
((xfs_agblock_t)((fsbno) & XFS_MASK32LO((mp)->m_sb.sb_agblklog)))
#define XFS_AGB_TO_DADDR(mp,agno,agbno) \
((xfs_daddr_t)XFS_FSB_TO_BB(mp, \
(xfs_fsblock_t)(agno) * (mp)->m_sb.sb_agblocks + (agbno)))
#define XFS_AG_DADDR(mp,agno,d) (XFS_AGB_TO_DADDR(mp, agno, 0) + (d))
/*
* For checking for bad ranges of xfs_daddr_t's, covering multiple
* allocation groups or a single xfs_daddr_t that's a superblock copy.
*/
#define XFS_AG_CHECK_DADDR(mp,d,len) \
((len) == 1 ? \
ASSERT((d) == XFS_SB_DADDR || \
XFS_DADDR_TO_AGBNO(mp, d) != XFS_SB_DADDR) : \
ASSERT(XFS_DADDR_TO_AGNO(mp, d) == \
XFS_DADDR_TO_AGNO(mp, (d) + (len) - 1)))
#endif /* __XFS_AG_H__ */

File diff suppressed because it is too large Load Diff

View File

@ -1,189 +0,0 @@
/*
* Copyright (c) 2000-2002,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
*/
#ifndef __XFS_ALLOC_H__
#define __XFS_ALLOC_H__
struct xfs_buf;
struct xfs_mount;
struct xfs_perag;
struct xfs_trans;
/*
* Freespace allocation types. Argument to xfs_alloc_[v]extent.
*/
typedef enum xfs_alloctype
{
XFS_ALLOCTYPE_ANY_AG, /* allocate anywhere, use rotor */
XFS_ALLOCTYPE_FIRST_AG, /* ... start at ag 0 */
XFS_ALLOCTYPE_START_AG, /* anywhere, start in this a.g. */
XFS_ALLOCTYPE_THIS_AG, /* anywhere in this a.g. */
XFS_ALLOCTYPE_START_BNO, /* near this block else anywhere */
XFS_ALLOCTYPE_NEAR_BNO, /* in this a.g. and near this block */
XFS_ALLOCTYPE_THIS_BNO /* at exactly this block */
} xfs_alloctype_t;
/*
* Flags for xfs_alloc_fix_freelist.
*/
#define XFS_ALLOC_FLAG_TRYLOCK 0x00000001 /* use trylock for buffer locking */
/*
* Argument structure for xfs_alloc routines.
* This is turned into a structure to avoid having 20 arguments passed
* down several levels of the stack.
*/
typedef struct xfs_alloc_arg {
struct xfs_trans *tp; /* transaction pointer */
struct xfs_mount *mp; /* file system mount point */
struct xfs_buf *agbp; /* buffer for a.g. freelist header */
struct xfs_perag *pag; /* per-ag struct for this agno */
xfs_fsblock_t fsbno; /* file system block number */
xfs_agnumber_t agno; /* allocation group number */
xfs_agblock_t agbno; /* allocation group-relative block # */
xfs_extlen_t minlen; /* minimum size of extent */
xfs_extlen_t maxlen; /* maximum size of extent */
xfs_extlen_t mod; /* mod value for extent size */
xfs_extlen_t prod; /* prod value for extent size */
xfs_extlen_t minleft; /* min blocks must be left after us */
xfs_extlen_t total; /* total blocks needed in xaction */
xfs_extlen_t alignment; /* align answer to multiple of this */
xfs_extlen_t minalignslop; /* slop for minlen+alignment calcs */
xfs_extlen_t len; /* output: actual size of extent */
xfs_alloctype_t type; /* allocation type XFS_ALLOCTYPE_... */
xfs_alloctype_t otype; /* original allocation type */
char wasdel; /* set if allocation was prev delayed */
char wasfromfl; /* set if allocation is from freelist */
char isfl; /* set if is freelist blocks - !acctg */
char userdata; /* set if this is user data */
} xfs_alloc_arg_t;
/*
* Defines for userdata
*/
#define XFS_ALLOC_USERDATA 1 /* allocation is for user data*/
#define XFS_ALLOC_INITIAL_USER_DATA 2 /* special case start of file */
#ifdef __KERNEL__
#if defined(XFS_ALLOC_TRACE)
/*
* Allocation tracing buffer size.
*/
#define XFS_ALLOC_TRACE_SIZE 4096
extern ktrace_t *xfs_alloc_trace_buf;
/*
* Types for alloc tracing.
*/
#define XFS_ALLOC_KTRACE_ALLOC 1
#define XFS_ALLOC_KTRACE_FREE 2
#define XFS_ALLOC_KTRACE_MODAGF 3
#define XFS_ALLOC_KTRACE_BUSY 4
#define XFS_ALLOC_KTRACE_UNBUSY 5
#define XFS_ALLOC_KTRACE_BUSYSEARCH 6
#endif
/*
* Compute and fill in value of m_ag_maxlevels.
*/
void
xfs_alloc_compute_maxlevels(
struct xfs_mount *mp); /* file system mount structure */
/*
* Get a block from the freelist.
* Returns with the buffer for the block gotten.
*/
int /* error */
xfs_alloc_get_freelist(
struct xfs_trans *tp, /* transaction pointer */
struct xfs_buf *agbp, /* buffer containing the agf structure */
xfs_agblock_t *bnop); /* block address retrieved from freelist */
/*
* Log the given fields from the agf structure.
*/
void
xfs_alloc_log_agf(
struct xfs_trans *tp, /* transaction pointer */
struct xfs_buf *bp, /* buffer for a.g. freelist header */
int fields);/* mask of fields to be logged (XFS_AGF_...) */
/*
* Interface for inode allocation to force the pag data to be initialized.
*/
int /* error */
xfs_alloc_pagf_init(
struct xfs_mount *mp, /* file system mount structure */
struct xfs_trans *tp, /* transaction pointer */
xfs_agnumber_t agno, /* allocation group number */
int flags); /* XFS_ALLOC_FLAGS_... */
/*
* Put the block on the freelist for the allocation group.
*/
int /* error */
xfs_alloc_put_freelist(
struct xfs_trans *tp, /* transaction pointer */
struct xfs_buf *agbp, /* buffer for a.g. freelist header */
struct xfs_buf *agflbp,/* buffer for a.g. free block array */
xfs_agblock_t bno); /* block being freed */
/*
* Read in the allocation group header (free/alloc section).
*/
int /* error */
xfs_alloc_read_agf(
struct xfs_mount *mp, /* mount point structure */
struct xfs_trans *tp, /* transaction pointer */
xfs_agnumber_t agno, /* allocation group number */
int flags, /* XFS_ALLOC_FLAG_... */
struct xfs_buf **bpp); /* buffer for the ag freelist header */
/*
* Allocate an extent (variable-size).
*/
int /* error */
xfs_alloc_vextent(
xfs_alloc_arg_t *args); /* allocation argument structure */
/*
* Free an extent.
*/
int /* error */
xfs_free_extent(
struct xfs_trans *tp, /* transaction pointer */
xfs_fsblock_t bno, /* starting block number of extent */
xfs_extlen_t len); /* length of extent */
void
xfs_alloc_mark_busy(xfs_trans_t *tp,
xfs_agnumber_t agno,
xfs_agblock_t bno,
xfs_extlen_t len);
void
xfs_alloc_clear_busy(xfs_trans_t *tp,
xfs_agnumber_t ag,
int idx);
#endif /* __KERNEL__ */
#endif /* __XFS_ALLOC_H__ */

File diff suppressed because it is too large Load Diff

View File

@ -1,159 +0,0 @@
/*
* Copyright (c) 2000,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
*/
#ifndef __XFS_ALLOC_BTREE_H__
#define __XFS_ALLOC_BTREE_H__
/*
* Freespace on-disk structures
*/
struct xfs_buf;
struct xfs_btree_cur;
struct xfs_btree_sblock;
struct xfs_mount;
/*
* There are two on-disk btrees, one sorted by blockno and one sorted
* by blockcount and blockno. All blocks look the same to make the code
* simpler; if we have time later, we'll make the optimizations.
*/
#define XFS_ABTB_MAGIC 0x41425442 /* 'ABTB' for bno tree */
#define XFS_ABTC_MAGIC 0x41425443 /* 'ABTC' for cnt tree */
/*
* Data record/key structure
*/
typedef struct xfs_alloc_rec {
__be32 ar_startblock; /* starting block number */
__be32 ar_blockcount; /* count of free blocks */
} xfs_alloc_rec_t, xfs_alloc_key_t;
typedef struct xfs_alloc_rec_incore {
xfs_agblock_t ar_startblock; /* starting block number */
xfs_extlen_t ar_blockcount; /* count of free blocks */
} xfs_alloc_rec_incore_t;
/* btree pointer type */
typedef __be32 xfs_alloc_ptr_t;
/* btree block header type */
typedef struct xfs_btree_sblock xfs_alloc_block_t;
#define XFS_BUF_TO_ALLOC_BLOCK(bp) ((xfs_alloc_block_t *)XFS_BUF_PTR(bp))
/*
* Real block structures have a size equal to the disk block size.
*/
#define XFS_ALLOC_BLOCK_SIZE(lev,cur) (1 << (cur)->bc_blocklog)
#define XFS_ALLOC_BLOCK_MAXRECS(lev,cur) ((cur)->bc_mp->m_alloc_mxr[lev != 0])
#define XFS_ALLOC_BLOCK_MINRECS(lev,cur) ((cur)->bc_mp->m_alloc_mnr[lev != 0])
/*
* Minimum and maximum blocksize and sectorsize.
* The blocksize upper limit is pretty much arbitrary.
* The sectorsize upper limit is due to sizeof(sb_sectsize).
*/
#define XFS_MIN_BLOCKSIZE_LOG 9 /* i.e. 512 bytes */
#define XFS_MAX_BLOCKSIZE_LOG 16 /* i.e. 65536 bytes */
#define XFS_MIN_BLOCKSIZE (1 << XFS_MIN_BLOCKSIZE_LOG)
#define XFS_MAX_BLOCKSIZE (1 << XFS_MAX_BLOCKSIZE_LOG)
#define XFS_MIN_SECTORSIZE_LOG 9 /* i.e. 512 bytes */
#define XFS_MAX_SECTORSIZE_LOG 15 /* i.e. 32768 bytes */
#define XFS_MIN_SECTORSIZE (1 << XFS_MIN_SECTORSIZE_LOG)
#define XFS_MAX_SECTORSIZE (1 << XFS_MAX_SECTORSIZE_LOG)
/*
* Block numbers in the AG:
* SB is sector 0, AGF is sector 1, AGI is sector 2, AGFL is sector 3.
*/
#define XFS_BNO_BLOCK(mp) ((xfs_agblock_t)(XFS_AGFL_BLOCK(mp) + 1))
#define XFS_CNT_BLOCK(mp) ((xfs_agblock_t)(XFS_BNO_BLOCK(mp) + 1))
/*
* Record, key, and pointer address macros for btree blocks.
*/
#define XFS_ALLOC_REC_ADDR(bb,i,cur) \
XFS_BTREE_REC_ADDR(XFS_ALLOC_BLOCK_SIZE(0,cur), xfs_alloc, \
bb, i, XFS_ALLOC_BLOCK_MAXRECS(0, cur))
#define XFS_ALLOC_KEY_ADDR(bb,i,cur) \
XFS_BTREE_KEY_ADDR(XFS_ALLOC_BLOCK_SIZE(1,cur), xfs_alloc, \
bb, i, XFS_ALLOC_BLOCK_MAXRECS(1, cur))
#define XFS_ALLOC_PTR_ADDR(bb,i,cur) \
XFS_BTREE_PTR_ADDR(XFS_ALLOC_BLOCK_SIZE(1,cur), xfs_alloc, \
bb, i, XFS_ALLOC_BLOCK_MAXRECS(1, cur))
/*
* Decrement cursor by one record at the level.
* For nonzero levels the leaf-ward information is untouched.
*/
extern int xfs_alloc_decrement(struct xfs_btree_cur *cur, int level, int *stat);
/*
* Delete the record pointed to by cur.
* The cursor refers to the place where the record was (could be inserted)
* when the operation returns.
*/
extern int xfs_alloc_delete(struct xfs_btree_cur *cur, int *stat);
/*
* Get the data from the pointed-to record.
*/
extern int xfs_alloc_get_rec(struct xfs_btree_cur *cur, xfs_agblock_t *bno,
xfs_extlen_t *len, int *stat);
/*
* Increment cursor by one record at the level.
* For nonzero levels the leaf-ward information is untouched.
*/
extern int xfs_alloc_increment(struct xfs_btree_cur *cur, int level, int *stat);
/*
* Insert the current record at the point referenced by cur.
* The cursor may be inconsistent on return if splits have been done.
*/
extern int xfs_alloc_insert(struct xfs_btree_cur *cur, int *stat);
/*
* Lookup the record equal to [bno, len] in the btree given by cur.
*/
extern int xfs_alloc_lookup_eq(struct xfs_btree_cur *cur, xfs_agblock_t bno,
xfs_extlen_t len, int *stat);
/*
* Lookup the first record greater than or equal to [bno, len]
* in the btree given by cur.
*/
extern int xfs_alloc_lookup_ge(struct xfs_btree_cur *cur, xfs_agblock_t bno,
xfs_extlen_t len, int *stat);
/*
* Lookup the first record less than or equal to [bno, len]
* in the btree given by cur.
*/
extern int xfs_alloc_lookup_le(struct xfs_btree_cur *cur, xfs_agblock_t bno,
xfs_extlen_t len, int *stat);
/*
* Update the record referred to by cur, to the value given by [bno, len].
* This either works (return 0) or gets an EFSCORRUPTED error.
*/
extern int xfs_alloc_update(struct xfs_btree_cur *cur, xfs_agblock_t bno,
xfs_extlen_t len);
#endif /* __XFS_ALLOC_BTREE_H__ */

View File

@ -1,239 +0,0 @@
/*
* Copyright (c) 2000-2002,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
*/
#ifndef __XFS_ARCH_H__
#define __XFS_ARCH_H__
#ifndef XFS_BIG_INUMS
# error XFS_BIG_INUMS must be defined true or false
#endif
#include <sys/endian.h>
#define __LITTLE_ENDIAN _LITTLE_ENDIAN
#define __BIG_ENDIAN _BIG_ENDIAN
#define __BYTE_ORDER _BYTE_ORDER
#define __user
/* Compatibiliy defines */
#define __swab16 __bswap16
#define __swab32 __bswap32
#define __swab64 __bswap64
#define ARCH_NOCONVERT 1
#if _BYTE_ORDER != _LITTLE_ENDIAN
#define XFS_NATIVE_HOST 1
# define ARCH_CONVERT ARCH_NOCONVERT
#else
#undef XFS_NATIVE_HOST
#define ARCH_CONVERT 0
#endif
#ifdef XFS_NATIVE_HOST
#define cpu_to_be16(val) ((__be16)(val))
#define cpu_to_be32(val) ((__be32)(val))
#define cpu_to_be64(val) ((__be64)(val))
#define be16_to_cpu(val) ((__uint16_t)(val))
#define be32_to_cpu(val) ((__uint32_t)(val))
#define be64_to_cpu(val) ((__uint64_t)(val))
#else
#define cpu_to_be16(val) (__swab16((__uint16_t)(val)))
#define cpu_to_be32(val) (__swab32((__uint32_t)(val)))
#define cpu_to_be64(val) (__swab64((__uint64_t)(val)))
#define be16_to_cpu(val) (__swab16((__be16)(val)))
#define be32_to_cpu(val) (__swab32((__be32)(val)))
#define be64_to_cpu(val) (__swab64((__be64)(val)))
#endif
//#endif /* __KERNEL__ */
/* do we need conversion? */
//#define ARCH_NOCONVERT 1
//#ifdef XFS_NATIVE_HOST
//# define ARCH_CONVERT ARCH_NOCONVERT
//#else
//# define ARCH_CONVERT 0
//#endif
/* generic swapping macros */
#ifndef HAVE_SWABMACROS
#define INT_SWAP16(type,var) ((typeof(type))(__swab16((__u16)(var))))
#define INT_SWAP32(type,var) ((typeof(type))(__swab32((__u32)(var))))
#define INT_SWAP64(type,var) ((typeof(type))(__swab64((__u64)(var))))
#endif
#define INT_SWAP(type, var) \
((sizeof(type) == 8) ? INT_SWAP64(type,var) : \
((sizeof(type) == 4) ? INT_SWAP32(type,var) : \
((sizeof(type) == 2) ? INT_SWAP16(type,var) : \
(var))))
/*
* get and set integers from potentially unaligned locations
*/
#define INT_GET_UNALIGNED_16_BE(pointer) \
((__u16)((((__u8*)(pointer))[0] << 8) | (((__u8*)(pointer))[1])))
#define INT_SET_UNALIGNED_16_BE(pointer,value) \
{ \
((__u8*)(pointer))[0] = (((value) >> 8) & 0xff); \
((__u8*)(pointer))[1] = (((value) ) & 0xff); \
}
/* define generic INT_ macros */
#define INT_GET(reference,arch) \
(((arch) == ARCH_NOCONVERT) \
? \
(reference) \
: \
INT_SWAP((reference),(reference)) \
)
/* does not return a value */
#define INT_SET(reference,arch,valueref) \
(__builtin_constant_p(valueref) ? \
(void)( (reference) = ( ((arch) != ARCH_NOCONVERT) ? (INT_SWAP((reference),(valueref))) : (valueref)) ) : \
(void)( \
((reference) = (valueref)), \
( ((arch) != ARCH_NOCONVERT) ? (reference) = INT_SWAP((reference),(reference)) : 0 ) \
) \
)
/* does not return a value */
#define INT_MOD_EXPR(reference,arch,code) \
(((arch) == ARCH_NOCONVERT) \
? \
(void)((reference) code) \
: \
(void)( \
(reference) = INT_GET((reference),arch) , \
((reference) code), \
INT_SET(reference, arch, reference) \
) \
)
/* does not return a value */
#define INT_MOD(reference,arch,delta) \
(void)( \
INT_MOD_EXPR(reference,arch,+=(delta)) \
)
/*
* INT_COPY - copy a value between two locations with the
* _same architecture_ but _potentially different sizes_
*
* if the types of the two parameters are equal or they are
* in native architecture, a simple copy is done
*
* otherwise, architecture conversions are done
*
*/
/* does not return a value */
#define INT_COPY(dst,src,arch) \
( \
((sizeof(dst) == sizeof(src)) || ((arch) == ARCH_NOCONVERT)) \
? \
(void)((dst) = (src)) \
: \
INT_SET(dst, arch, INT_GET(src, arch)) \
)
/*
* INT_XLATE - copy a value in either direction between two locations
* with different architectures
*
* dir < 0 - copy from memory to buffer (native to arch)
* dir > 0 - copy from buffer to memory (arch to native)
*/
/* does not return a value */
#define INT_XLATE(buf,mem,dir,arch) {\
ASSERT(dir); \
if (dir>0) { \
(mem)=INT_GET(buf, arch); \
} else { \
INT_SET(buf, arch, mem); \
} \
}
static inline void be16_add(__be16 *a, __s16 b)
{
*a = cpu_to_be16(be16_to_cpu(*a) + b);
}
static inline void be32_add(__be32 *a, __s32 b)
{
*a = cpu_to_be32(be32_to_cpu(*a) + b);
}
static inline void be64_add(__be64 *a, __s64 b)
{
*a = cpu_to_be64(be64_to_cpu(*a) + b);
}
/*
* In directories inode numbers are stored as unaligned arrays of unsigned
* 8bit integers on disk.
*
* For v1 directories or v2 directories that contain inode numbers that
* do not fit into 32bit the array has eight members, but the first member
* is always zero:
*
* |unused|48-55|40-47|32-39|24-31|16-23| 8-15| 0- 7|
*
* For v2 directories that only contain entries with inode numbers that fit
* into 32bits a four-member array is used:
*
* |24-31|16-23| 8-15| 0- 7|
*/
#define XFS_GET_DIR_INO4(di) \
(((__u32)(di).i[0] << 24) | ((di).i[1] << 16) | ((di).i[2] << 8) | ((di).i[3]))
#define XFS_PUT_DIR_INO4(from, di) \
do { \
(di).i[0] = (((from) & 0xff000000ULL) >> 24); \
(di).i[1] = (((from) & 0x00ff0000ULL) >> 16); \
(di).i[2] = (((from) & 0x0000ff00ULL) >> 8); \
(di).i[3] = ((from) & 0x000000ffULL); \
} while (0)
#define XFS_DI_HI(di) \
(((__u32)(di).i[1] << 16) | ((di).i[2] << 8) | ((di).i[3]))
#define XFS_DI_LO(di) \
(((__u32)(di).i[4] << 24) | ((di).i[5] << 16) | ((di).i[6] << 8) | ((di).i[7]))
#define XFS_GET_DIR_INO8(di) \
(((xfs_ino_t)XFS_DI_LO(di) & 0xffffffffULL) | \
((xfs_ino_t)XFS_DI_HI(di) << 32))
#define XFS_PUT_DIR_INO8(from, di) \
do { \
(di).i[0] = 0; \
(di).i[1] = (((from) & 0x00ff000000000000ULL) >> 48); \
(di).i[2] = (((from) & 0x0000ff0000000000ULL) >> 40); \
(di).i[3] = (((from) & 0x000000ff00000000ULL) >> 32); \
(di).i[4] = (((from) & 0x00000000ff000000ULL) >> 24); \
(di).i[5] = (((from) & 0x0000000000ff0000ULL) >> 16); \
(di).i[6] = (((from) & 0x000000000000ff00ULL) >> 8); \
(di).i[7] = ((from) & 0x00000000000000ffULL); \
} while (0)
#endif /* __XFS_ARCH_H__ */

File diff suppressed because it is too large Load Diff

View File

@ -1,172 +0,0 @@
/*
* Copyright (c) 2000,2002-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
*/
#ifndef __XFS_ATTR_H__
#define __XFS_ATTR_H__
/*
* xfs_attr.h
*
* Large attribute lists are structured around Btrees where all the data
* elements are in the leaf nodes. Attribute names are hashed into an int,
* then that int is used as the index into the Btree. Since the hashval
* of an attribute name may not be unique, we may have duplicate keys.
* The internal links in the Btree are logical block offsets into the file.
*
* Small attribute lists use a different format and are packed as tightly
* as possible so as to fit into the literal area of the inode.
*/
/*========================================================================
* External interfaces
*========================================================================*/
struct cred;
struct xfs_vnode;
typedef int (*attrset_t)(struct xfs_vnode *, char *, void *, size_t, int);
typedef int (*attrget_t)(struct xfs_vnode *, char *, void *, size_t, int);
typedef int (*attrremove_t)(struct xfs_vnode *, char *, int);
typedef int (*attrexists_t)(struct xfs_vnode *);
typedef int (*attrcapable_t)(struct xfs_vnode *, struct cred *);
typedef struct attrnames {
char * attr_name;
unsigned int attr_namelen;
unsigned int attr_flag;
attrget_t attr_get;
attrset_t attr_set;
attrremove_t attr_remove;
attrexists_t attr_exists;
attrcapable_t attr_capable;
} attrnames_t;
#define ATTR_NAMECOUNT 4
extern struct attrnames attr_user;
extern struct attrnames attr_secure;
extern struct attrnames attr_system;
extern struct attrnames attr_trusted;
extern struct attrnames *attr_namespaces[ATTR_NAMECOUNT];
extern attrnames_t *attr_lookup_namespace(char *, attrnames_t **, int);
extern int attr_generic_list(struct xfs_vnode *, void *, size_t, int, ssize_t *);
#define ATTR_DONTFOLLOW 0x0001 /* -- unused, from IRIX -- */
#define ATTR_ROOT 0x0002 /* use attrs in root (trusted) namespace */
#define ATTR_TRUST 0x0004 /* -- unused, from IRIX -- */
#define ATTR_SECURE 0x0008 /* use attrs in security namespace */
#define ATTR_CREATE 0x0010 /* pure create: fail if attr already exists */
#define ATTR_REPLACE 0x0020 /* pure set: fail if attr does not exist */
#define ATTR_SYSTEM 0x0100 /* use attrs in system (pseudo) namespace */
#define ATTR_KERNACCESS 0x0400 /* [kernel] iaccess, inode held io-locked */
#define ATTR_KERNOTIME 0x1000 /* [kernel] don't update inode timestamps */
#define ATTR_KERNOVAL 0x2000 /* [kernel] get attr size only, not value */
#define ATTR_KERNAMELS 0x4000 /* [kernel] list attr names (simple list) */
#define ATTR_KERNORMALS 0x0800 /* [kernel] normal attr list: user+secure */
#define ATTR_KERNROOTLS 0x8000 /* [kernel] include root in the attr list */
#define ATTR_KERNFULLS (ATTR_KERNORMALS|ATTR_KERNROOTLS)
/*
* The maximum size (into the kernel or returned from the kernel) of an
* attribute value or the buffer used for an attr_list() call. Larger
* sizes will result in an ERANGE return code.
*/
#define ATTR_MAX_VALUELEN (64*1024) /* max length of a value */
/*
* Define how lists of attribute names are returned to the user from
* the attr_list() call. A large, 32bit aligned, buffer is passed in
* along with its size. We put an array of offsets at the top that each
* reference an attrlist_ent_t and pack the attrlist_ent_t's at the bottom.
*/
typedef struct attrlist {
__s32 al_count; /* number of entries in attrlist */
__s32 al_more; /* T/F: more attrs (do call again) */
__s32 al_offset[1]; /* byte offsets of attrs [var-sized] */
} attrlist_t;
/*
* Show the interesting info about one attribute. This is what the
* al_offset[i] entry points to.
*/
typedef struct attrlist_ent { /* data from attr_list() */
__u32 a_valuelen; /* number bytes in value of attr */
char a_name[1]; /* attr name (NULL terminated) */
} attrlist_ent_t;
/*
* Given a pointer to the (char*) buffer containing the attr_list() result,
* and an index, return a pointer to the indicated attribute in the buffer.
*/
#define ATTR_ENTRY(buffer, index) \
((attrlist_ent_t *) \
&((char *)buffer)[ ((attrlist_t *)(buffer))->al_offset[index] ])
/*
* Multi-attribute operation vector.
*/
typedef struct attr_multiop {
int am_opcode; /* operation to perform (ATTR_OP_GET, etc.) */
int am_error; /* [out arg] result of this sub-op (an errno) */
char *am_attrname; /* attribute name to work with */
char *am_attrvalue; /* [in/out arg] attribute value (raw bytes) */
int am_length; /* [in/out arg] length of value */
int am_flags; /* bitwise OR of attr API flags defined above */
} attr_multiop_t;
#define ATTR_OP_GET 1 /* return the indicated attr's value */
#define ATTR_OP_SET 2 /* set/create the indicated attr/value pair */
#define ATTR_OP_REMOVE 3 /* remove the indicated attr */
/*
* Kernel-internal version of the attrlist cursor.
*/
typedef struct attrlist_cursor_kern {
__u32 hashval; /* hash value of next entry to add */
__u32 blkno; /* block containing entry (suggestion) */
__u32 offset; /* offset in list of equal-hashvals */
__u16 pad1; /* padding to match user-level */
__u8 pad2; /* padding to match user-level */
__u8 initted; /* T/F: cursor has been initialized */
} attrlist_cursor_kern_t;
/*========================================================================
* Function prototypes for the kernel.
*========================================================================*/
struct xfs_inode;
struct attrlist_cursor_kern;
struct xfs_da_args;
/*
* Overall external interface routines.
*/
int xfs_attr_get(bhv_desc_t *, const char *, char *, int *, int, struct cred *);
int xfs_attr_set(bhv_desc_t *, const char *, char *, int, int, struct cred *);
int xfs_attr_remove(bhv_desc_t *, const char *, int, struct cred *);
int xfs_attr_list(bhv_desc_t *, char *, int, int,
struct attrlist_cursor_kern *, struct cred *);
int xfs_attr_inactive(struct xfs_inode *dp);
int xfs_attr_shortform_getvalue(struct xfs_da_args *);
int xfs_attr_fetch(struct xfs_inode *, const char *, int,
char *, int *, int, struct cred *);
#endif /* __XFS_ATTR_H__ */

File diff suppressed because it is too large Load Diff

View File

@ -1,282 +0,0 @@
/*
* Copyright (c) 2000,2002-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
*/
#ifndef __XFS_ATTR_LEAF_H__
#define __XFS_ATTR_LEAF_H__
/*
* Attribute storage layout, internal structure, access macros, etc.
*
* Attribute lists are structured around Btrees where all the data
* elements are in the leaf nodes. Attribute names are hashed into an int,
* then that int is used as the index into the Btree. Since the hashval
* of an attribute name may not be unique, we may have duplicate keys. The
* internal links in the Btree are logical block offsets into the file.
*/
struct attrlist;
struct attrlist_cursor_kern;
struct attrnames;
struct xfs_dabuf;
struct xfs_da_args;
struct xfs_da_state;
struct xfs_da_state_blk;
struct xfs_inode;
struct xfs_trans;
/*========================================================================
* Attribute structure when equal to XFS_LBSIZE(mp) bytes.
*========================================================================*/
/*
* This is the structure of the leaf nodes in the Btree.
*
* Struct leaf_entry's are packed from the top. Name/values grow from the
* bottom but are not packed. The freemap contains run-length-encoded entries
* for the free bytes after the leaf_entry's, but only the N largest such,
* smaller runs are dropped. When the freemap doesn't show enough space
* for an allocation, we compact the name/value area and try again. If we
* still don't have enough space, then we have to split the block. The
* name/value structs (both local and remote versions) must be 32bit aligned.
*
* Since we have duplicate hash keys, for each key that matches, compare
* the actual name string. The root and intermediate node search always
* takes the first-in-the-block key match found, so we should only have
* to work "forw"ard. If none matches, continue with the "forw"ard leaf
* nodes until the hash key changes or the attribute name is found.
*
* We store the fact that an attribute is a ROOT/USER/SECURE attribute in
* the leaf_entry. The namespaces are independent only because we also look
* at the namespace bit when we are looking for a matching attribute name.
*
* We also store an "incomplete" bit in the leaf_entry. It shows that an
* attribute is in the middle of being created and should not be shown to
* the user if we crash during the time that the bit is set. We clear the
* bit when we have finished setting up the attribute. We do this because
* we cannot create some large attributes inside a single transaction, and we
* need some indication that we weren't finished if we crash in the middle.
*/
#define XFS_ATTR_LEAF_MAPSIZE 3 /* how many freespace slots */
typedef struct xfs_attr_leaf_map { /* RLE map of free bytes */
__be16 base; /* base of free region */
__be16 size; /* length of free region */
} xfs_attr_leaf_map_t;
typedef struct xfs_attr_leaf_hdr { /* constant-structure header block */
xfs_da_blkinfo_t info; /* block type, links, etc. */
__be16 count; /* count of active leaf_entry's */
__be16 usedbytes; /* num bytes of names/values stored */
__be16 firstused; /* first used byte in name area */
__u8 holes; /* != 0 if blk needs compaction */
__u8 pad1;
xfs_attr_leaf_map_t freemap[XFS_ATTR_LEAF_MAPSIZE];
/* N largest free regions */
} xfs_attr_leaf_hdr_t;
typedef struct xfs_attr_leaf_entry { /* sorted on key, not name */
__be32 hashval; /* hash value of name */
__be16 nameidx; /* index into buffer of name/value */
__u8 flags; /* LOCAL/ROOT/SECURE/INCOMPLETE flag */
__u8 pad2; /* unused pad byte */
} xfs_attr_leaf_entry_t;
typedef struct xfs_attr_leaf_name_local {
__be16 valuelen; /* number of bytes in value */
__u8 namelen; /* length of name bytes */
__u8 nameval[1]; /* name/value bytes */
} xfs_attr_leaf_name_local_t;
typedef struct xfs_attr_leaf_name_remote {
__be32 valueblk; /* block number of value bytes */
__be32 valuelen; /* number of bytes in value */
__u8 namelen; /* length of name bytes */
__u8 name[1]; /* name bytes */
} xfs_attr_leaf_name_remote_t;
typedef struct xfs_attr_leafblock {
xfs_attr_leaf_hdr_t hdr; /* constant-structure header block */
xfs_attr_leaf_entry_t entries[1]; /* sorted on key, not name */
xfs_attr_leaf_name_local_t namelist; /* grows from bottom of buf */
xfs_attr_leaf_name_remote_t valuelist; /* grows from bottom of buf */
} xfs_attr_leafblock_t;
/*
* Flags used in the leaf_entry[i].flags field.
* NOTE: the INCOMPLETE bit must not collide with the flags bits specified
* on the system call, they are "or"ed together for various operations.
*/
#define XFS_ATTR_LOCAL_BIT 0 /* attr is stored locally */
#define XFS_ATTR_ROOT_BIT 1 /* limit access to trusted attrs */
#define XFS_ATTR_SECURE_BIT 2 /* limit access to secure attrs */
#define XFS_ATTR_INCOMPLETE_BIT 7 /* attr in middle of create/delete */
#define XFS_ATTR_LOCAL (1 << XFS_ATTR_LOCAL_BIT)
#define XFS_ATTR_ROOT (1 << XFS_ATTR_ROOT_BIT)
#define XFS_ATTR_SECURE (1 << XFS_ATTR_SECURE_BIT)
#define XFS_ATTR_INCOMPLETE (1 << XFS_ATTR_INCOMPLETE_BIT)
/*
* Alignment for namelist and valuelist entries (since they are mixed
* there can be only one alignment value)
*/
#define XFS_ATTR_LEAF_NAME_ALIGN ((uint)sizeof(xfs_dablk_t))
/*
* Cast typed pointers for "local" and "remote" name/value structs.
*/
#define XFS_ATTR_LEAF_NAME_REMOTE(leafp,idx) \
xfs_attr_leaf_name_remote(leafp,idx)
static inline xfs_attr_leaf_name_remote_t *
xfs_attr_leaf_name_remote(xfs_attr_leafblock_t *leafp, int idx)
{
return (xfs_attr_leaf_name_remote_t *)
&((char *)leafp)[be16_to_cpu(leafp->entries[idx].nameidx)];
}
#define XFS_ATTR_LEAF_NAME_LOCAL(leafp,idx) \
xfs_attr_leaf_name_local(leafp,idx)
static inline xfs_attr_leaf_name_local_t *
xfs_attr_leaf_name_local(xfs_attr_leafblock_t *leafp, int idx)
{
return (xfs_attr_leaf_name_local_t *)
&((char *)leafp)[be16_to_cpu(leafp->entries[idx].nameidx)];
}
#define XFS_ATTR_LEAF_NAME(leafp,idx) \
xfs_attr_leaf_name(leafp,idx)
static inline char *xfs_attr_leaf_name(xfs_attr_leafblock_t *leafp, int idx)
{
return &((char *)leafp)[be16_to_cpu(leafp->entries[idx].nameidx)];
}
/*
* Calculate total bytes used (including trailing pad for alignment) for
* a "local" name/value structure, a "remote" name/value structure, and
* a pointer which might be either.
*/
#define XFS_ATTR_LEAF_ENTSIZE_REMOTE(nlen) \
xfs_attr_leaf_entsize_remote(nlen)
static inline int xfs_attr_leaf_entsize_remote(int nlen)
{
return ((uint)sizeof(xfs_attr_leaf_name_remote_t) - 1 + (nlen) + \
XFS_ATTR_LEAF_NAME_ALIGN - 1) & ~(XFS_ATTR_LEAF_NAME_ALIGN - 1);
}
#define XFS_ATTR_LEAF_ENTSIZE_LOCAL(nlen,vlen) \
xfs_attr_leaf_entsize_local(nlen,vlen)
static inline int xfs_attr_leaf_entsize_local(int nlen, int vlen)
{
return ((uint)sizeof(xfs_attr_leaf_name_local_t) - 1 + (nlen) + (vlen) +
XFS_ATTR_LEAF_NAME_ALIGN - 1) & ~(XFS_ATTR_LEAF_NAME_ALIGN - 1);
}
#define XFS_ATTR_LEAF_ENTSIZE_LOCAL_MAX(bsize) \
xfs_attr_leaf_entsize_local_max(bsize)
static inline int xfs_attr_leaf_entsize_local_max(int bsize)
{
return (((bsize) >> 1) + ((bsize) >> 2));
}
/*========================================================================
* Structure used to pass context around among the routines.
*========================================================================*/
typedef struct xfs_attr_list_context {
struct xfs_inode *dp; /* inode */
struct attrlist_cursor_kern *cursor;/* position in list */
struct attrlist *alist; /* output buffer */
int count; /* num used entries */
int dupcnt; /* count dup hashvals seen */
int bufsize;/* total buffer size */
int firstu; /* first used byte in buffer */
int flags; /* from VOP call */
int resynch;/* T/F: resynch with cursor */
} xfs_attr_list_context_t;
/*
* Used to keep a list of "remote value" extents when unlinking an inode.
*/
typedef struct xfs_attr_inactive_list {
xfs_dablk_t valueblk; /* block number of value bytes */
int valuelen; /* number of bytes in value */
} xfs_attr_inactive_list_t;
/*========================================================================
* Function prototypes for the kernel.
*========================================================================*/
/*
* Internal routines when attribute fork size < XFS_LITINO(mp).
*/
void xfs_attr_shortform_create(struct xfs_da_args *args);
void xfs_attr_shortform_add(struct xfs_da_args *args, int forkoff);
int xfs_attr_shortform_lookup(struct xfs_da_args *args);
int xfs_attr_shortform_to_leaf(struct xfs_da_args *args);
int xfs_attr_shortform_remove(struct xfs_da_args *args);
int xfs_attr_shortform_list(struct xfs_attr_list_context *context);
int xfs_attr_shortform_allfit(struct xfs_dabuf *bp, struct xfs_inode *dp);
int xfs_attr_shortform_bytesfit(xfs_inode_t *dp, int bytes);
/*
* Internal routines when attribute fork size == XFS_LBSIZE(mp).
*/
int xfs_attr_leaf_to_node(struct xfs_da_args *args);
int xfs_attr_leaf_to_shortform(struct xfs_dabuf *bp,
struct xfs_da_args *args, int forkoff);
int xfs_attr_leaf_clearflag(struct xfs_da_args *args);
int xfs_attr_leaf_setflag(struct xfs_da_args *args);
int xfs_attr_leaf_flipflags(xfs_da_args_t *args);
/*
* Routines used for growing the Btree.
*/
int xfs_attr_leaf_split(struct xfs_da_state *state,
struct xfs_da_state_blk *oldblk,
struct xfs_da_state_blk *newblk);
int xfs_attr_leaf_lookup_int(struct xfs_dabuf *leaf,
struct xfs_da_args *args);
int xfs_attr_leaf_getvalue(struct xfs_dabuf *bp, struct xfs_da_args *args);
int xfs_attr_leaf_add(struct xfs_dabuf *leaf_buffer,
struct xfs_da_args *args);
int xfs_attr_leaf_remove(struct xfs_dabuf *leaf_buffer,
struct xfs_da_args *args);
int xfs_attr_leaf_list_int(struct xfs_dabuf *bp,
struct xfs_attr_list_context *context);
/*
* Routines used for shrinking the Btree.
*/
int xfs_attr_leaf_toosmall(struct xfs_da_state *state, int *retval);
void xfs_attr_leaf_unbalance(struct xfs_da_state *state,
struct xfs_da_state_blk *drop_blk,
struct xfs_da_state_blk *save_blk);
int xfs_attr_root_inactive(struct xfs_trans **trans, struct xfs_inode *dp);
/*
* Utility routines.
*/
xfs_dahash_t xfs_attr_leaf_lasthash(struct xfs_dabuf *bp, int *count);
int xfs_attr_leaf_order(struct xfs_dabuf *leaf1_bp,
struct xfs_dabuf *leaf2_bp);
int xfs_attr_leaf_newentsize(int namelen, int valuelen, int blocksize,
int *local);
int xfs_attr_rolltrans(struct xfs_trans **transp, struct xfs_inode *dp);
#endif /* __XFS_ATTR_LEAF_H__ */

View File

@ -1,114 +0,0 @@
/*
* Copyright (c) 2000,2002,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
*/
#ifndef __XFS_ATTR_SF_H__
#define __XFS_ATTR_SF_H__
/*
* Attribute storage when stored inside the inode.
*
* Small attribute lists are packed as tightly as possible so as
* to fit into the literal area of the inode.
*/
struct xfs_inode;
/*
* Entries are packed toward the top as tight as possible.
*/
typedef struct xfs_attr_shortform {
struct xfs_attr_sf_hdr { /* constant-structure header block */
__be16 totsize; /* total bytes in shortform list */
__u8 count; /* count of active entries */
} hdr;
struct xfs_attr_sf_entry {
__uint8_t namelen; /* actual length of name (no NULL) */
__uint8_t valuelen; /* actual length of value (no NULL) */
__uint8_t flags; /* flags bits (see xfs_attr_leaf.h) */
__uint8_t nameval[1]; /* name & value bytes concatenated */
} list[1]; /* variable sized array */
} xfs_attr_shortform_t;
typedef struct xfs_attr_sf_hdr xfs_attr_sf_hdr_t;
typedef struct xfs_attr_sf_entry xfs_attr_sf_entry_t;
/*
* We generate this then sort it, attr_list() must return things in hash-order.
*/
typedef struct xfs_attr_sf_sort {
__uint8_t entno; /* entry number in original list */
__uint8_t namelen; /* length of name value (no null) */
__uint8_t valuelen; /* length of value */
__uint8_t flags; /* flags bits (see xfs_attr_leaf.h) */
xfs_dahash_t hash; /* this entry's hash value */
char *name; /* name value, pointer into buffer */
} xfs_attr_sf_sort_t;
#define XFS_ATTR_SF_ENTSIZE_BYNAME(nlen,vlen) /* space name/value uses */ \
(((int)sizeof(xfs_attr_sf_entry_t)-1 + (nlen)+(vlen)))
#define XFS_ATTR_SF_ENTSIZE_MAX /* max space for name&value */ \
((1 << (NBBY*(int)sizeof(__uint8_t))) - 1)
#define XFS_ATTR_SF_ENTSIZE(sfep) /* space an entry uses */ \
((int)sizeof(xfs_attr_sf_entry_t)-1 + (sfep)->namelen+(sfep)->valuelen)
#define XFS_ATTR_SF_NEXTENTRY(sfep) /* next entry in struct */ \
((xfs_attr_sf_entry_t *)((char *)(sfep) + XFS_ATTR_SF_ENTSIZE(sfep)))
#define XFS_ATTR_SF_TOTSIZE(dp) /* total space in use */ \
(be16_to_cpu(((xfs_attr_shortform_t *) \
((dp)->i_afp->if_u1.if_data))->hdr.totsize))
#if defined(XFS_ATTR_TRACE)
/*
* Kernel tracing support for attribute lists
*/
struct xfs_attr_list_context;
struct xfs_da_intnode;
struct xfs_da_node_entry;
struct xfs_attr_leafblock;
#define XFS_ATTR_TRACE_SIZE 4096 /* size of global trace buffer */
extern ktrace_t *xfs_attr_trace_buf;
/*
* Trace record types.
*/
#define XFS_ATTR_KTRACE_L_C 1 /* context */
#define XFS_ATTR_KTRACE_L_CN 2 /* context, node */
#define XFS_ATTR_KTRACE_L_CB 3 /* context, btree */
#define XFS_ATTR_KTRACE_L_CL 4 /* context, leaf */
void xfs_attr_trace_l_c(char *where, struct xfs_attr_list_context *context);
void xfs_attr_trace_l_cn(char *where, struct xfs_attr_list_context *context,
struct xfs_da_intnode *node);
void xfs_attr_trace_l_cb(char *where, struct xfs_attr_list_context *context,
struct xfs_da_node_entry *btree);
void xfs_attr_trace_l_cl(char *where, struct xfs_attr_list_context *context,
struct xfs_attr_leafblock *leaf);
void xfs_attr_trace_enter(int type, char *where,
__psunsigned_t a2, __psunsigned_t a3,
__psunsigned_t a4, __psunsigned_t a5,
__psunsigned_t a6, __psunsigned_t a7,
__psunsigned_t a8, __psunsigned_t a9,
__psunsigned_t a10, __psunsigned_t a11,
__psunsigned_t a12, __psunsigned_t a13,
__psunsigned_t a14, __psunsigned_t a15);
#else
#define xfs_attr_trace_l_c(w,c)
#define xfs_attr_trace_l_cn(w,c,n)
#define xfs_attr_trace_l_cb(w,c,b)
#define xfs_attr_trace_l_cl(w,c,l)
#endif /* XFS_ATTR_TRACE */
#endif /* __XFS_ATTR_SF_H__ */

View File

@ -1,203 +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"
/*
* Source file used to associate/disassociate behaviors with virtualized
* objects. See xfs_behavior.h for more information about behaviors, etc.
*
* The implementation is split between functions in this file and macros
* in xfs_behavior.h.
*/
/*
* Insert a new behavior descriptor into a behavior chain.
*
* The behavior chain is ordered based on the 'position' number which
* lives in the first field of the ops vector (higher numbers first).
*
* Attempts to insert duplicate ops result in an EINVAL return code.
* Otherwise, return 0 to indicate success.
*/
int
bhv_insert(bhv_head_t *bhp, bhv_desc_t *bdp)
{
bhv_desc_t *curdesc, *prev;
int position;
/*
* Validate the position value of the new behavior.
*/
position = BHV_POSITION(bdp);
ASSERT(position >= BHV_POSITION_BASE && position <= BHV_POSITION_TOP);
/*
* Find location to insert behavior. Check for duplicates.
*/
prev = NULL;
for (curdesc = bhp->bh_first;
curdesc != NULL;
curdesc = curdesc->bd_next) {
/* Check for duplication. */
if (curdesc->bd_ops == bdp->bd_ops) {
ASSERT(0);
return EINVAL;
}
/* Find correct position */
if (position >= BHV_POSITION(curdesc)) {
ASSERT(position != BHV_POSITION(curdesc));
break; /* found it */
}
prev = curdesc;
}
if (prev == NULL) {
/* insert at front of chain */
bdp->bd_next = bhp->bh_first;
bhp->bh_first = bdp;
} else {
/* insert after prev */
bdp->bd_next = prev->bd_next;
prev->bd_next = bdp;
}
return 0;
}
/*
* Remove a behavior descriptor from a position in a behavior chain;
* the position is guaranteed not to be the first position.
* Should only be called by the bhv_remove() macro.
*/
void
bhv_remove_not_first(bhv_head_t *bhp, bhv_desc_t *bdp)
{
bhv_desc_t *curdesc, *prev;
ASSERT(bhp->bh_first != NULL);
ASSERT(bhp->bh_first->bd_next != NULL);
prev = bhp->bh_first;
for (curdesc = bhp->bh_first->bd_next;
curdesc != NULL;
curdesc = curdesc->bd_next) {
if (curdesc == bdp)
break; /* found it */
prev = curdesc;
}
ASSERT(curdesc == bdp);
prev->bd_next = bdp->bd_next; /* remove from after prev */
}
/*
* Look for a specific ops vector on the specified behavior chain.
* Return the associated behavior descriptor. Or NULL, if not found.
*/
bhv_desc_t *
bhv_lookup(bhv_head_t *bhp, void *ops)
{
bhv_desc_t *curdesc;
for (curdesc = bhp->bh_first;
curdesc != NULL;
curdesc = curdesc->bd_next) {
if (curdesc->bd_ops == ops)
return curdesc;
}
return NULL;
}
/*
* Looks for the first behavior within a specified range of positions.
* Return the associated behavior descriptor. Or NULL, if none found.
*/
bhv_desc_t *
bhv_lookup_range(bhv_head_t *bhp, int low, int high)
{
bhv_desc_t *curdesc;
for (curdesc = bhp->bh_first;
curdesc != NULL;
curdesc = curdesc->bd_next) {
int position = BHV_POSITION(curdesc);
if (position <= high) {
if (position >= low)
return curdesc;
return NULL;
}
}
return NULL;
}
/*
* Return the base behavior in the chain, or NULL if the chain
* is empty.
*
* The caller has not read locked the behavior chain, so acquire the
* lock before traversing the chain.
*/
bhv_desc_t *
bhv_base(bhv_head_t *bhp)
{
bhv_desc_t *curdesc;
for (curdesc = bhp->bh_first;
curdesc != NULL;
curdesc = curdesc->bd_next) {
if (curdesc->bd_next == NULL) {
return curdesc;
}
}
return NULL;
}
void
bhv_head_init(
bhv_head_t *bhp,
char *name)
{
bhp->bh_first = NULL;
}
void
bhv_insert_initial(
bhv_head_t *bhp,
bhv_desc_t *bdp)
{
ASSERT(bhp->bh_first == NULL);
(bhp)->bh_first = bdp;
}
void
bhv_head_destroy(
bhv_head_t *bhp)
{
ASSERT(bhp->bh_first == NULL);
}

View File

@ -1,190 +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
*/
#ifndef __XFS_BEHAVIOR_H__
#define __XFS_BEHAVIOR_H__
/*
* Header file used to associate behaviors with virtualized objects.
*
* A virtualized object is an internal, virtualized representation of
* OS entities such as persistent files, processes, or sockets. Examples
* of virtualized objects include vnodes, vprocs, and vsockets. Often
* a virtualized object is referred to simply as an "object."
*
* A behavior is essentially an implementation layer associated with
* an object. Multiple behaviors for an object are chained together,
* the order of chaining determining the order of invocation. Each
* behavior of a given object implements the same set of interfaces
* (e.g., the VOP interfaces).
*
* Behaviors may be dynamically inserted into an object's behavior chain,
* such that the addition is transparent to consumers that already have
* references to the object. Typically, a given behavior will be inserted
* at a particular location in the behavior chain. Insertion of new
* behaviors is synchronized with operations-in-progress (oip's) so that
* the oip's always see a consistent view of the chain.
*
* The term "interposition" is used to refer to the act of inserting
* a behavior such that it interposes on (i.e., is inserted in front
* of) a particular other behavior. A key example of this is when a
* system implementing distributed single system image wishes to
* interpose a distribution layer (providing distributed coherency)
* in front of an object that is otherwise only accessed locally.
*
* Note that the traditional vnode/inode combination is simply a virtualized
* object that has exactly one associated behavior.
*
* Behavior synchronization is logic which is necessary under certain
* circumstances that there is no conflict between ongoing operations
* traversing the behavior chain and those dynamically modifying the
* behavior chain. Because behavior synchronization adds extra overhead
* to virtual operation invocation, we want to restrict, as much as
* we can, the requirement for this extra code, to those situations
* in which it is truly necessary.
*
* Behavior synchronization is needed whenever there's at least one class
* of object in the system for which:
* 1) multiple behaviors for a given object are supported,
* -- AND --
* 2a) insertion of a new behavior can happen dynamically at any time during
* the life of an active object,
* -- AND --
* 3a) insertion of a new behavior needs to synchronize with existing
* ops-in-progress.
* -- OR --
* 3b) multiple different behaviors can be dynamically inserted at
* any time during the life of an active object
* -- OR --
* 3c) removal of a behavior can occur at any time during the life of
* an active object.
* -- OR --
* 2b) removal of a behavior can occur at any time during the life of an
* active object
*
*/
struct bhv_head_lock;
/*
* Behavior head. Head of the chain of behaviors.
* Contained within each virtualized object data structure.
*/
typedef struct bhv_head {
struct bhv_desc *bh_first; /* first behavior in chain */
struct bhv_head_lock *bh_lockp; /* pointer to lock info struct */
} bhv_head_t;
/*
* Behavior descriptor. Descriptor associated with each behavior.
* Contained within the behavior's private data structure.
*/
typedef struct bhv_desc {
void *bd_pdata; /* private data for this behavior */
void *bd_vobj; /* virtual object associated with */
void *bd_ops; /* ops for this behavior */
struct bhv_desc *bd_next; /* next behavior in chain */
} bhv_desc_t;
/*
* Behavior identity field. A behavior's identity determines the position
* where it lives within a behavior chain, and it's always the first field
* of the behavior's ops vector. The optional id field further identifies the
* subsystem responsible for the behavior.
*/
typedef struct bhv_identity {
__u16 bi_id; /* owning subsystem id */
__u16 bi_position; /* position in chain */
} bhv_identity_t;
typedef bhv_identity_t bhv_position_t;
#define BHV_IDENTITY_INIT(id,pos) {id, pos}
#define BHV_IDENTITY_INIT_POSITION(pos) BHV_IDENTITY_INIT(0, pos)
/*
* Define boundaries of position values.
*/
#define BHV_POSITION_INVALID 0 /* invalid position number */
#define BHV_POSITION_BASE 1 /* base (last) implementation layer */
#define BHV_POSITION_TOP 63 /* top (first) implementation layer */
/*
* Plumbing macros.
*/
#define BHV_HEAD_FIRST(bhp) (ASSERT((bhp)->bh_first), (bhp)->bh_first)
#define BHV_NEXT(bdp) (ASSERT((bdp)->bd_next), (bdp)->bd_next)
#define BHV_NEXTNULL(bdp) ((bdp)->bd_next)
#define BHV_VOBJ(bdp) (ASSERT((bdp)->bd_vobj), (bdp)->bd_vobj)
#define BHV_VOBJNULL(bdp) ((bdp)->bd_vobj)
#define BHV_PDATA(bdp) (bdp)->bd_pdata
#define BHV_OPS(bdp) (bdp)->bd_ops
#define BHV_IDENTITY(bdp) ((bhv_identity_t *)(bdp)->bd_ops)
#define BHV_POSITION(bdp) (BHV_IDENTITY(bdp)->bi_position)
extern void bhv_head_init(bhv_head_t *, char *);
extern void bhv_head_destroy(bhv_head_t *);
extern int bhv_insert(bhv_head_t *, bhv_desc_t *);
extern void bhv_insert_initial(bhv_head_t *, bhv_desc_t *);
/*
* Initialize a new behavior descriptor.
* Arguments:
* bdp - pointer to behavior descriptor
* pdata - pointer to behavior's private data
* vobj - pointer to associated virtual object
* ops - pointer to ops for this behavior
*/
#define bhv_desc_init(bdp, pdata, vobj, ops) \
{ \
(bdp)->bd_pdata = pdata; \
(bdp)->bd_vobj = vobj; \
(bdp)->bd_ops = ops; \
(bdp)->bd_next = NULL; \
}
/*
* Remove a behavior descriptor from a behavior chain.
*/
#define bhv_remove(bhp, bdp) \
{ \
if ((bhp)->bh_first == (bdp)) { \
/* \
* Remove from front of chain. \
* Atomic wrt oip's. \
*/ \
(bhp)->bh_first = (bdp)->bd_next; \
} else { \
/* remove from non-front of chain */ \
bhv_remove_not_first(bhp, bdp); \
} \
(bdp)->bd_vobj = NULL; \
}
/*
* Behavior module prototypes.
*/
extern void bhv_remove_not_first(bhv_head_t *bhp, bhv_desc_t *bdp);
extern bhv_desc_t * bhv_lookup(bhv_head_t *bhp, void *ops);
extern bhv_desc_t * bhv_lookup_range(bhv_head_t *bhp, int low, int high);
extern bhv_desc_t * bhv_base(bhv_head_t *bhp);
/* No bhv locking on Linux */
#define bhv_lookup_unlocked bhv_lookup
#define bhv_base_unlocked bhv_base
#endif /* __XFS_BEHAVIOR_H__ */

View File

@ -1,296 +0,0 @@
/*
* Copyright (c) 2000-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"
#include "xfs_bit.h"
#include "xfs_log.h"
#include "xfs_trans.h"
#include "xfs_buf_item.h"
/*
* XFS bit manipulation routines, used in non-realtime code.
*/
#ifndef HAVE_ARCH_HIGHBIT
/*
* Index of high bit number in byte, -1 for none set, 0..7 otherwise.
*/
STATIC const char xfs_highbit[256] = {
-1, 0, 1, 1, 2, 2, 2, 2, /* 00 .. 07 */
3, 3, 3, 3, 3, 3, 3, 3, /* 08 .. 0f */
4, 4, 4, 4, 4, 4, 4, 4, /* 10 .. 17 */
4, 4, 4, 4, 4, 4, 4, 4, /* 18 .. 1f */
5, 5, 5, 5, 5, 5, 5, 5, /* 20 .. 27 */
5, 5, 5, 5, 5, 5, 5, 5, /* 28 .. 2f */
5, 5, 5, 5, 5, 5, 5, 5, /* 30 .. 37 */
5, 5, 5, 5, 5, 5, 5, 5, /* 38 .. 3f */
6, 6, 6, 6, 6, 6, 6, 6, /* 40 .. 47 */
6, 6, 6, 6, 6, 6, 6, 6, /* 48 .. 4f */
6, 6, 6, 6, 6, 6, 6, 6, /* 50 .. 57 */
6, 6, 6, 6, 6, 6, 6, 6, /* 58 .. 5f */
6, 6, 6, 6, 6, 6, 6, 6, /* 60 .. 67 */
6, 6, 6, 6, 6, 6, 6, 6, /* 68 .. 6f */
6, 6, 6, 6, 6, 6, 6, 6, /* 70 .. 77 */
6, 6, 6, 6, 6, 6, 6, 6, /* 78 .. 7f */
7, 7, 7, 7, 7, 7, 7, 7, /* 80 .. 87 */
7, 7, 7, 7, 7, 7, 7, 7, /* 88 .. 8f */
7, 7, 7, 7, 7, 7, 7, 7, /* 90 .. 97 */
7, 7, 7, 7, 7, 7, 7, 7, /* 98 .. 9f */
7, 7, 7, 7, 7, 7, 7, 7, /* a0 .. a7 */
7, 7, 7, 7, 7, 7, 7, 7, /* a8 .. af */
7, 7, 7, 7, 7, 7, 7, 7, /* b0 .. b7 */
7, 7, 7, 7, 7, 7, 7, 7, /* b8 .. bf */
7, 7, 7, 7, 7, 7, 7, 7, /* c0 .. c7 */
7, 7, 7, 7, 7, 7, 7, 7, /* c8 .. cf */
7, 7, 7, 7, 7, 7, 7, 7, /* d0 .. d7 */
7, 7, 7, 7, 7, 7, 7, 7, /* d8 .. df */
7, 7, 7, 7, 7, 7, 7, 7, /* e0 .. e7 */
7, 7, 7, 7, 7, 7, 7, 7, /* e8 .. ef */
7, 7, 7, 7, 7, 7, 7, 7, /* f0 .. f7 */
7, 7, 7, 7, 7, 7, 7, 7, /* f8 .. ff */
};
#endif
/*
* Count of bits set in byte, 0..8.
*/
static const char xfs_countbit[256] = {
0, 1, 1, 2, 1, 2, 2, 3, /* 00 .. 07 */
1, 2, 2, 3, 2, 3, 3, 4, /* 08 .. 0f */
1, 2, 2, 3, 2, 3, 3, 4, /* 10 .. 17 */
2, 3, 3, 4, 3, 4, 4, 5, /* 18 .. 1f */
1, 2, 2, 3, 2, 3, 3, 4, /* 20 .. 27 */
2, 3, 3, 4, 3, 4, 4, 5, /* 28 .. 2f */
2, 3, 3, 4, 3, 4, 4, 5, /* 30 .. 37 */
3, 4, 4, 5, 4, 5, 5, 6, /* 38 .. 3f */
1, 2, 2, 3, 2, 3, 3, 4, /* 40 .. 47 */
2, 3, 3, 4, 3, 4, 4, 5, /* 48 .. 4f */
2, 3, 3, 4, 3, 4, 4, 5, /* 50 .. 57 */
3, 4, 4, 5, 4, 5, 5, 6, /* 58 .. 5f */
2, 3, 3, 4, 3, 4, 4, 5, /* 60 .. 67 */
3, 4, 4, 5, 4, 5, 5, 6, /* 68 .. 6f */
3, 4, 4, 5, 4, 5, 5, 6, /* 70 .. 77 */
4, 5, 5, 6, 5, 6, 6, 7, /* 78 .. 7f */
1, 2, 2, 3, 2, 3, 3, 4, /* 80 .. 87 */
2, 3, 3, 4, 3, 4, 4, 5, /* 88 .. 8f */
2, 3, 3, 4, 3, 4, 4, 5, /* 90 .. 97 */
3, 4, 4, 5, 4, 5, 5, 6, /* 98 .. 9f */
2, 3, 3, 4, 3, 4, 4, 5, /* a0 .. a7 */
3, 4, 4, 5, 4, 5, 5, 6, /* a8 .. af */
3, 4, 4, 5, 4, 5, 5, 6, /* b0 .. b7 */
4, 5, 5, 6, 5, 6, 6, 7, /* b8 .. bf */
2, 3, 3, 4, 3, 4, 4, 5, /* c0 .. c7 */
3, 4, 4, 5, 4, 5, 5, 6, /* c8 .. cf */
3, 4, 4, 5, 4, 5, 5, 6, /* d0 .. d7 */
4, 5, 5, 6, 5, 6, 6, 7, /* d8 .. df */
3, 4, 4, 5, 4, 5, 5, 6, /* e0 .. e7 */
4, 5, 5, 6, 5, 6, 6, 7, /* e8 .. ef */
4, 5, 5, 6, 5, 6, 6, 7, /* f0 .. f7 */
5, 6, 6, 7, 6, 7, 7, 8, /* f8 .. ff */
};
/*
* xfs_highbit32: get high bit set out of 32-bit argument, -1 if none set.
*/
int
xfs_highbit32(
__uint32_t v)
{
#ifdef HAVE_ARCH_HIGHBIT
return highbit32(v);
#else
int i;
if (v & 0xffff0000)
if (v & 0xff000000)
i = 24;
else
i = 16;
else if (v & 0x0000ffff)
if (v & 0x0000ff00)
i = 8;
else
i = 0;
else
return -1;
return i + xfs_highbit[(v >> i) & 0xff];
#endif
}
/*
* xfs_lowbit64: get low bit set out of 64-bit argument, -1 if none set.
*/
int
xfs_lowbit64(
__uint64_t v)
{
__uint32_t w = (__uint32_t)v;
int n = 0;
if (w) { /* lower bits */
n = ffs(w);
} else { /* upper bits */
w = (__uint32_t)(v >> 32);
if (w && (n = ffs(w)))
n += 32;
}
return n - 1;
}
/*
* xfs_highbit64: get high bit set out of 64-bit argument, -1 if none set.
*/
int
xfs_highbit64(
__uint64_t v)
{
__uint32_t h = (__uint32_t)(v >> 32);
if (h)
return xfs_highbit32(h) + 32;
return xfs_highbit32((__uint32_t)v);
}
/*
* Count the number of bits set in the bitmap starting with bit
* start_bit. Size is the size of the bitmap in words.
*
* Do the counting by mapping a byte value to the number of set
* bits for that value using the xfs_countbit array, i.e.
* xfs_countbit[0] == 0, xfs_countbit[1] == 1, xfs_countbit[2] == 1,
* xfs_countbit[3] == 2, etc.
*/
int
xfs_count_bits(uint *map, uint size, uint start_bit)
{
register int bits;
register unsigned char *bytep;
register unsigned char *end_map;
int byte_bit;
bits = 0;
end_map = (char*)(map + size);
bytep = (char*)(map + (start_bit & ~0x7));
byte_bit = start_bit & 0x7;
/*
* If the caller fell off the end of the map, return 0.
*/
if (bytep >= end_map) {
return (0);
}
/*
* If start_bit is not byte aligned, then process the
* first byte separately.
*/
if (byte_bit != 0) {
/*
* Shift off the bits we don't want to look at,
* before indexing into xfs_countbit.
*/
bits += xfs_countbit[(*bytep >> byte_bit)];
bytep++;
}
/*
* Count the bits in each byte until the end of the bitmap.
*/
while (bytep < end_map) {
bits += xfs_countbit[*bytep];
bytep++;
}
return (bits);
}
/*
* Count the number of contiguous bits set in the bitmap starting with bit
* start_bit. Size is the size of the bitmap in words.
*/
int
xfs_contig_bits(uint *map, uint size, uint start_bit)
{
uint * p = ((unsigned int *) map) + (start_bit >> BIT_TO_WORD_SHIFT);
uint result = 0;
uint tmp;
size <<= BIT_TO_WORD_SHIFT;
ASSERT(start_bit < size);
size -= start_bit & ~(NBWORD - 1);
start_bit &= (NBWORD - 1);
if (start_bit) {
tmp = *p++;
/* set to one first offset bits prior to start */
tmp |= (~0U >> (NBWORD-start_bit));
if (tmp != ~0U)
goto found;
result += NBWORD;
size -= NBWORD;
}
while (size) {
if ((tmp = *p++) != ~0U)
goto found;
result += NBWORD;
size -= NBWORD;
}
return result - start_bit;
found:
return result + ffz(tmp) - start_bit;
}
/*
* This takes the bit number to start looking from and
* returns the next set bit from there. It returns -1
* if there are no more bits set or the start bit is
* beyond the end of the bitmap.
*
* Size is the number of words, not bytes, in the bitmap.
*/
int xfs_next_bit(uint *map, uint size, uint start_bit)
{
uint * p = ((unsigned int *) map) + (start_bit >> BIT_TO_WORD_SHIFT);
uint result = start_bit & ~(NBWORD - 1);
uint tmp;
size <<= BIT_TO_WORD_SHIFT;
if (start_bit >= size)
return -1;
size -= result;
start_bit &= (NBWORD - 1);
if (start_bit) {
tmp = *p++;
/* set to zero first offset bits prior to start */
tmp &= (~0U << start_bit);
if (tmp != 0U)
goto found;
result += NBWORD;
size -= NBWORD;
}
while (size) {
if ((tmp = *p++) != 0U)
goto found;
result += NBWORD;
size -= NBWORD;
}
return -1;
found:
return result + ffs(tmp) - 1;
}

View File

@ -1,67 +0,0 @@
/*
* Copyright (c) 2000,2002,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
*/
#ifndef __XFS_BIT_H__
#define __XFS_BIT_H__
/*
* XFS bit manipulation routines.
*/
/*
* masks with n high/low bits set, 32-bit values & 64-bit values
*/
#define XFS_MASK32HI(n) xfs_mask32hi(n)
static inline __uint32_t xfs_mask32hi(int n)
{
return (__uint32_t)-1 << (32 - (n));
}
#define XFS_MASK64HI(n) xfs_mask64hi(n)
static inline __uint64_t xfs_mask64hi(int n)
{
return (__uint64_t)-1 << (64 - (n));
}
#define XFS_MASK32LO(n) xfs_mask32lo(n)
static inline __uint32_t xfs_mask32lo(int n)
{
return ((__uint32_t)1 << (n)) - 1;
}
#define XFS_MASK64LO(n) xfs_mask64lo(n)
static inline __uint64_t xfs_mask64lo(int n)
{
return ((__uint64_t)1 << (n)) - 1;
}
/* Get high bit set out of 32-bit argument, -1 if none set */
extern int xfs_highbit32(__uint32_t v);
/* Get low bit set out of 64-bit argument, -1 if none set */
extern int xfs_lowbit64(__uint64_t v);
/* Get high bit set out of 64-bit argument, -1 if none set */
extern int xfs_highbit64(__uint64_t);
/* Count set bits in map starting with start_bit */
extern int xfs_count_bits(uint *map, uint size, uint start_bit);
/* Count continuous one bits in map starting with start_bit */
extern int xfs_contig_bits(uint *map, uint size, uint start_bit);
/* Find next set bit in map */
extern int xfs_next_bit(uint *map, uint size, uint start_bit);
#endif /* __XFS_BIT_H__ */

File diff suppressed because it is too large Load Diff

View File

@ -1,386 +0,0 @@
/*
* Copyright (c) 2000-2006 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
*/
#ifndef __XFS_BMAP_H__
#define __XFS_BMAP_H__
struct getbmap;
struct xfs_bmbt_irec;
struct xfs_ifork;
struct xfs_inode;
struct xfs_mount;
struct xfs_trans;
/*
* DELTA: describe a change to the in-core extent list.
*
* Internally the use of xed_blockount is somewhat funky.
* xed_blockcount contains an offset much of the time because this
* makes merging changes easier. (xfs_fileoff_t and xfs_filblks_t are
* the same underlying type).
*/
typedef struct xfs_extdelta
{
xfs_fileoff_t xed_startoff; /* offset of range */
xfs_filblks_t xed_blockcount; /* blocks in range */
} xfs_extdelta_t;
/*
* List of extents to be free "later".
* The list is kept sorted on xbf_startblock.
*/
typedef struct xfs_bmap_free_item
{
xfs_fsblock_t xbfi_startblock;/* starting fs block number */
xfs_extlen_t xbfi_blockcount;/* number of blocks in extent */
struct xfs_bmap_free_item *xbfi_next; /* link to next entry */
} xfs_bmap_free_item_t;
/*
* Header for free extent list.
*/
typedef struct xfs_bmap_free
{
xfs_bmap_free_item_t *xbf_first; /* list of to-be-free extents */
int xbf_count; /* count of items on list */
int xbf_low; /* kludge: alloc in low mode */
} xfs_bmap_free_t;
#define XFS_BMAP_MAX_NMAP 4
/*
* Flags for xfs_bmapi
*/
#define XFS_BMAPI_WRITE 0x001 /* write operation: allocate space */
#define XFS_BMAPI_DELAY 0x002 /* delayed write operation */
#define XFS_BMAPI_ENTIRE 0x004 /* return entire extent, not trimmed */
#define XFS_BMAPI_METADATA 0x008 /* mapping metadata not user data */
#define XFS_BMAPI_EXACT 0x010 /* allocate only to spec'd bounds */
#define XFS_BMAPI_ATTRFORK 0x020 /* use attribute fork not data */
#define XFS_BMAPI_ASYNC 0x040 /* bunmapi xactions can be async */
#define XFS_BMAPI_RSVBLOCKS 0x080 /* OK to alloc. reserved data blocks */
#define XFS_BMAPI_PREALLOC 0x100 /* preallocation op: unwritten space */
#define XFS_BMAPI_IGSTATE 0x200 /* Ignore state - */
/* combine contig. space */
#define XFS_BMAPI_CONTIG 0x400 /* must allocate only one extent */
/* XFS_BMAPI_DIRECT_IO 0x800 */
#define XFS_BMAPI_CONVERT 0x1000 /* unwritten extent conversion - */
/* need write cache flushing and no */
/* additional allocation alignments */
#define XFS_BMAPI_AFLAG(w) xfs_bmapi_aflag(w)
static inline int xfs_bmapi_aflag(int w)
{
return (w == XFS_ATTR_FORK ? XFS_BMAPI_ATTRFORK : 0);
}
/*
* Special values for xfs_bmbt_irec_t br_startblock field.
*/
#define DELAYSTARTBLOCK ((xfs_fsblock_t)-1LL)
#define HOLESTARTBLOCK ((xfs_fsblock_t)-2LL)
#define XFS_BMAP_INIT(flp,fbp) xfs_bmap_init(flp,fbp)
static inline void xfs_bmap_init(xfs_bmap_free_t *flp, xfs_fsblock_t *fbp)
{
((flp)->xbf_first = NULL, (flp)->xbf_count = 0, \
(flp)->xbf_low = 0, *(fbp) = NULLFSBLOCK);
}
/*
* Argument structure for xfs_bmap_alloc.
*/
typedef struct xfs_bmalloca {
xfs_fsblock_t firstblock; /* i/o first block allocated */
xfs_fsblock_t rval; /* starting block of new extent */
xfs_fileoff_t off; /* offset in file filling in */
struct xfs_trans *tp; /* transaction pointer */
struct xfs_inode *ip; /* incore inode pointer */
struct xfs_bmbt_irec *prevp; /* extent before the new one */
struct xfs_bmbt_irec *gotp; /* extent after, or delayed */
xfs_extlen_t alen; /* i/o length asked/allocated */
xfs_extlen_t total; /* total blocks needed for xaction */
xfs_extlen_t minlen; /* mininum allocation size (blocks) */
xfs_extlen_t minleft; /* amount must be left after alloc */
char eof; /* set if allocating past last extent */
char wasdel; /* replacing a delayed allocation */
char userdata;/* set if is user data */
char low; /* low on space, using seq'l ags */
char aeof; /* allocated space at eof */
char conv; /* overwriting unwritten extents */
} xfs_bmalloca_t;
#ifdef __KERNEL__
#if defined(XFS_BMAP_TRACE)
/*
* Trace operations for bmap extent tracing
*/
#define XFS_BMAP_KTRACE_DELETE 1
#define XFS_BMAP_KTRACE_INSERT 2
#define XFS_BMAP_KTRACE_PRE_UP 3
#define XFS_BMAP_KTRACE_POST_UP 4
#define XFS_BMAP_TRACE_SIZE 4096 /* size of global trace buffer */
#define XFS_BMAP_KTRACE_SIZE 32 /* size of per-inode trace buffer */
extern ktrace_t *xfs_bmap_trace_buf;
/*
* Add bmap trace insert entries for all the contents of the extent list.
*/
void
xfs_bmap_trace_exlist(
char *fname, /* function name */
struct xfs_inode *ip, /* incore inode pointer */
xfs_extnum_t cnt, /* count of entries in list */
int whichfork); /* data or attr fork */
#else
#define xfs_bmap_trace_exlist(f,ip,c,w)
#endif
/*
* Convert inode from non-attributed to attributed.
* Must not be in a transaction, ip must not be locked.
*/
int /* error code */
xfs_bmap_add_attrfork(
struct xfs_inode *ip, /* incore inode pointer */
int size, /* space needed for new attribute */
int rsvd); /* flag for reserved block allocation */
/*
* Add the extent to the list of extents to be free at transaction end.
* The list is maintained sorted (by block number).
*/
void
xfs_bmap_add_free(
xfs_fsblock_t bno, /* fs block number of extent */
xfs_filblks_t len, /* length of extent */
xfs_bmap_free_t *flist, /* list of extents */
struct xfs_mount *mp); /* mount point structure */
/*
* Routine to clean up the free list data structure when
* an error occurs during a transaction.
*/
void
xfs_bmap_cancel(
xfs_bmap_free_t *flist); /* free list to clean up */
/*
* Compute and fill in the value of the maximum depth of a bmap btree
* in this filesystem. Done once, during mount.
*/
void
xfs_bmap_compute_maxlevels(
struct xfs_mount *mp, /* file system mount structure */
int whichfork); /* data or attr fork */
/*
* Routine to be called at transaction's end by xfs_bmapi, xfs_bunmapi
* caller. Frees all the extents that need freeing, which must be done
* last due to locking considerations.
*
* Return 1 if the given transaction was committed and a new one allocated,
* and 0 otherwise.
*/
int /* error */
xfs_bmap_finish(
struct xfs_trans **tp, /* transaction pointer addr */
xfs_bmap_free_t *flist, /* i/o: list extents to free */
xfs_fsblock_t firstblock, /* controlled a.g. for allocs */
int *committed); /* xact committed or not */
/*
* Returns the file-relative block number of the first unused block in the file.
* This is the lowest-address hole if the file has holes, else the first block
* past the end of file.
*/
int /* error */
xfs_bmap_first_unused(
struct xfs_trans *tp, /* transaction pointer */
struct xfs_inode *ip, /* incore inode */
xfs_extlen_t len, /* size of hole to find */
xfs_fileoff_t *unused, /* unused block num */
int whichfork); /* data or attr fork */
/*
* Returns the file-relative block number of the last block + 1 before
* last_block (input value) in the file.
* This is not based on i_size, it is based on the extent list.
* Returns 0 for local files, as they do not have an extent list.
*/
int /* error */
xfs_bmap_last_before(
struct xfs_trans *tp, /* transaction pointer */
struct xfs_inode *ip, /* incore inode */
xfs_fileoff_t *last_block, /* last block */
int whichfork); /* data or attr fork */
/*
* Returns the file-relative block number of the first block past eof in
* the file. This is not based on i_size, it is based on the extent list.
* Returns 0 for local files, as they do not have an extent list.
*/
int /* error */
xfs_bmap_last_offset(
struct xfs_trans *tp, /* transaction pointer */
struct xfs_inode *ip, /* incore inode */
xfs_fileoff_t *unused, /* last block num */
int whichfork); /* data or attr fork */
/*
* Returns whether the selected fork of the inode has exactly one
* block or not. For the data fork we check this matches di_size,
* implying the file's range is 0..bsize-1.
*/
int
xfs_bmap_one_block(
struct xfs_inode *ip, /* incore inode */
int whichfork); /* data or attr fork */
/*
* Read in the extents to iu_extents.
* All inode fields are set up by caller, we just traverse the btree
* and copy the records in.
*/
int /* error */
xfs_bmap_read_extents(
struct xfs_trans *tp, /* transaction pointer */
struct xfs_inode *ip, /* incore inode */
int whichfork); /* data or attr fork */
/*
* Map file blocks to filesystem blocks.
* File range is given by the bno/len pair.
* Adds blocks to file if a write ("flags & XFS_BMAPI_WRITE" set)
* into a hole or past eof.
* Only allocates blocks from a single allocation group,
* to avoid locking problems.
* The returned value in "firstblock" from the first call in a transaction
* must be remembered and presented to subsequent calls in "firstblock".
* An upper bound for the number of blocks to be allocated is supplied to
* the first call in "total"; if no allocation group has that many free
* blocks then the call will fail (return NULLFSBLOCK in "firstblock").
*/
int /* error */
xfs_bmapi(
struct xfs_trans *tp, /* transaction pointer */
struct xfs_inode *ip, /* incore inode */
xfs_fileoff_t bno, /* starting file offs. mapped */
xfs_filblks_t len, /* length to map in file */
int flags, /* XFS_BMAPI_... */
xfs_fsblock_t *firstblock, /* first allocated block
controls a.g. for allocs */
xfs_extlen_t total, /* total blocks needed */
struct xfs_bmbt_irec *mval, /* output: map values */
int *nmap, /* i/o: mval size/count */
xfs_bmap_free_t *flist, /* i/o: list extents to free */
xfs_extdelta_t *delta); /* o: change made to incore
extents */
/*
* Map file blocks to filesystem blocks, simple version.
* One block only, read-only.
* For flags, only the XFS_BMAPI_ATTRFORK flag is examined.
* For the other flag values, the effect is as if XFS_BMAPI_METADATA
* was set and all the others were clear.
*/
int /* error */
xfs_bmapi_single(
struct xfs_trans *tp, /* transaction pointer */
struct xfs_inode *ip, /* incore inode */
int whichfork, /* data or attr fork */
xfs_fsblock_t *fsb, /* output: mapped block */
xfs_fileoff_t bno); /* starting file offs. mapped */
/*
* Unmap (remove) blocks from a file.
* If nexts is nonzero then the number of extents to remove is limited to
* that value. If not all extents in the block range can be removed then
* *done is set.
*/
int /* error */
xfs_bunmapi(
struct xfs_trans *tp, /* transaction pointer */
struct xfs_inode *ip, /* incore inode */
xfs_fileoff_t bno, /* starting offset to unmap */
xfs_filblks_t len, /* length to unmap in file */
int flags, /* XFS_BMAPI_... */
xfs_extnum_t nexts, /* number of extents max */
xfs_fsblock_t *firstblock, /* first allocated block
controls a.g. for allocs */
xfs_bmap_free_t *flist, /* i/o: list extents to free */
xfs_extdelta_t *delta, /* o: change made to incore
extents */
int *done); /* set if not done yet */
/*
* Fcntl interface to xfs_bmapi.
*/
int /* error code */
xfs_getbmap(
bhv_desc_t *bdp, /* XFS behavior descriptor*/
struct getbmap *bmv, /* user bmap structure */
void __user *ap, /* pointer to user's array */
int iflags); /* interface flags */
/*
* Check if the endoff is outside the last extent. If so the caller will grow
* the allocation to a stripe unit boundary
*/
int
xfs_bmap_eof(
struct xfs_inode *ip,
xfs_fileoff_t endoff,
int whichfork,
int *eof);
/*
* Count fsblocks of the given fork.
*/
int
xfs_bmap_count_blocks(
xfs_trans_t *tp,
struct xfs_inode *ip,
int whichfork,
int *count);
/*
* Check an extent list, which has just been read, for
* any bit in the extent flag field.
*/
int
xfs_check_nostate_extents(
struct xfs_ifork *ifp,
xfs_extnum_t idx,
xfs_extnum_t num);
/*
* Search the extent records for the entry containing block bno.
* If bno lies in a hole, point to the next entry. If bno lies
* past eof, *eofp will be set, and *prevp will contain the last
* entry (null if none). Else, *lastxp will be set to the index
* of the found entry; *gotp will contain the entry.
*/
xfs_bmbt_rec_t *
xfs_bmap_search_multi_extents(struct xfs_ifork *, xfs_fileoff_t, int *,
xfs_extnum_t *, xfs_bmbt_irec_t *, xfs_bmbt_irec_t *);
#endif /* __KERNEL__ */
#endif /* __XFS_BMAP_H__ */

File diff suppressed because it is too large Load Diff

View File

@ -1,377 +0,0 @@
/*
* Copyright (c) 2000,2002-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
*/
#ifndef __XFS_BMAP_BTREE_H__
#define __XFS_BMAP_BTREE_H__
#define XFS_BMAP_MAGIC 0x424d4150 /* 'BMAP' */
struct xfs_btree_cur;
struct xfs_btree_lblock;
struct xfs_mount;
struct xfs_inode;
/*
* Bmap root header, on-disk form only.
*/
typedef struct xfs_bmdr_block {
__be16 bb_level; /* 0 is a leaf */
__be16 bb_numrecs; /* current # of data records */
} xfs_bmdr_block_t;
/*
* Bmap btree record and extent descriptor.
* For 32-bit kernels,
* l0:31 is an extent flag (value 1 indicates non-normal).
* l0:0-30 and l1:9-31 are startoff.
* l1:0-8, l2:0-31, and l3:21-31 are startblock.
* l3:0-20 are blockcount.
* For 64-bit kernels,
* l0:63 is an extent flag (value 1 indicates non-normal).
* l0:9-62 are startoff.
* l0:0-8 and l1:21-63 are startblock.
* l1:0-20 are blockcount.
*/
#ifndef XFS_NATIVE_HOST
#define BMBT_TOTAL_BITLEN 128 /* 128 bits, 16 bytes */
#define BMBT_EXNTFLAG_BITOFF 0
#define BMBT_EXNTFLAG_BITLEN 1
#define BMBT_STARTOFF_BITOFF (BMBT_EXNTFLAG_BITOFF + BMBT_EXNTFLAG_BITLEN)
#define BMBT_STARTOFF_BITLEN 54
#define BMBT_STARTBLOCK_BITOFF (BMBT_STARTOFF_BITOFF + BMBT_STARTOFF_BITLEN)
#define BMBT_STARTBLOCK_BITLEN 52
#define BMBT_BLOCKCOUNT_BITOFF \
(BMBT_STARTBLOCK_BITOFF + BMBT_STARTBLOCK_BITLEN)
#define BMBT_BLOCKCOUNT_BITLEN (BMBT_TOTAL_BITLEN - BMBT_BLOCKCOUNT_BITOFF)
#else
#define BMBT_TOTAL_BITLEN 128 /* 128 bits, 16 bytes */
#define BMBT_EXNTFLAG_BITOFF 63
#define BMBT_EXNTFLAG_BITLEN 1
#define BMBT_STARTOFF_BITOFF (BMBT_EXNTFLAG_BITOFF - BMBT_STARTOFF_BITLEN)
#define BMBT_STARTOFF_BITLEN 54
#define BMBT_STARTBLOCK_BITOFF 85 /* 128 - 43 (other 9 is in first word) */
#define BMBT_STARTBLOCK_BITLEN 52
#define BMBT_BLOCKCOUNT_BITOFF 64 /* Start of second 64 bit container */
#define BMBT_BLOCKCOUNT_BITLEN 21
#endif /* XFS_NATIVE_HOST */
#define BMBT_USE_64 1
typedef struct xfs_bmbt_rec_32
{
__uint32_t l0, l1, l2, l3;
} xfs_bmbt_rec_32_t;
typedef struct xfs_bmbt_rec_64
{
__uint64_t l0, l1;
} xfs_bmbt_rec_64_t;
typedef __uint64_t xfs_bmbt_rec_base_t; /* use this for casts */
typedef xfs_bmbt_rec_64_t xfs_bmbt_rec_t, xfs_bmdr_rec_t;
/*
* Values and macros for delayed-allocation startblock fields.
*/
#define STARTBLOCKVALBITS 17
#define STARTBLOCKMASKBITS (15 + XFS_BIG_BLKNOS * 20)
#define DSTARTBLOCKMASKBITS (15 + 20)
#define STARTBLOCKMASK \
(((((xfs_fsblock_t)1) << STARTBLOCKMASKBITS) - 1) << STARTBLOCKVALBITS)
#define DSTARTBLOCKMASK \
(((((xfs_dfsbno_t)1) << DSTARTBLOCKMASKBITS) - 1) << STARTBLOCKVALBITS)
#define ISNULLSTARTBLOCK(x) isnullstartblock(x)
static inline int isnullstartblock(xfs_fsblock_t x)
{
return ((x) & STARTBLOCKMASK) == STARTBLOCKMASK;
}
#define ISNULLDSTARTBLOCK(x) isnulldstartblock(x)
static inline int isnulldstartblock(xfs_dfsbno_t x)
{
return ((x) & DSTARTBLOCKMASK) == DSTARTBLOCKMASK;
}
#define NULLSTARTBLOCK(k) nullstartblock(k)
static inline xfs_fsblock_t nullstartblock(int k)
{
ASSERT(k < (1 << STARTBLOCKVALBITS));
return STARTBLOCKMASK | (k);
}
#define STARTBLOCKVAL(x) startblockval(x)
static inline xfs_filblks_t startblockval(xfs_fsblock_t x)
{
return (xfs_filblks_t)((x) & ~STARTBLOCKMASK);
}
/*
* Possible extent formats.
*/
typedef enum {
XFS_EXTFMT_NOSTATE = 0,
XFS_EXTFMT_HASSTATE
} xfs_exntfmt_t;
/*
* Possible extent states.
*/
typedef enum {
XFS_EXT_NORM, XFS_EXT_UNWRITTEN,
XFS_EXT_DMAPI_OFFLINE, XFS_EXT_INVALID
} xfs_exntst_t;
/*
* Extent state and extent format macros.
*/
#define XFS_EXTFMT_INODE(x) \
(XFS_SB_VERSION_HASEXTFLGBIT(&((x)->i_mount->m_sb)) ? \
XFS_EXTFMT_HASSTATE : XFS_EXTFMT_NOSTATE)
#define ISUNWRITTEN(x) ((x)->br_state == XFS_EXT_UNWRITTEN)
/*
* Incore version of above.
*/
typedef struct xfs_bmbt_irec
{
xfs_fileoff_t br_startoff; /* starting file offset */
xfs_fsblock_t br_startblock; /* starting block number */
xfs_filblks_t br_blockcount; /* number of blocks */
xfs_exntst_t br_state; /* extent state */
} xfs_bmbt_irec_t;
/*
* Key structure for non-leaf levels of the tree.
*/
typedef struct xfs_bmbt_key
{
xfs_dfiloff_t br_startoff; /* starting file offset */
} xfs_bmbt_key_t, xfs_bmdr_key_t;
typedef xfs_dfsbno_t xfs_bmbt_ptr_t, xfs_bmdr_ptr_t; /* btree pointer type */
/* btree block header type */
typedef struct xfs_btree_lblock xfs_bmbt_block_t;
#define XFS_BUF_TO_BMBT_BLOCK(bp) ((xfs_bmbt_block_t *)XFS_BUF_PTR(bp))
#define XFS_BMAP_IBLOCK_SIZE(lev,cur) (1 << (cur)->bc_blocklog)
#define XFS_BMAP_RBLOCK_DSIZE(lev,cur) ((cur)->bc_private.b.forksize)
#define XFS_BMAP_RBLOCK_ISIZE(lev,cur) \
((int)XFS_IFORK_PTR((cur)->bc_private.b.ip, \
(cur)->bc_private.b.whichfork)->if_broot_bytes)
#define XFS_BMAP_BLOCK_DSIZE(lev,cur) \
(((lev) == (cur)->bc_nlevels - 1 ? \
XFS_BMAP_RBLOCK_DSIZE(lev,cur) : XFS_BMAP_IBLOCK_SIZE(lev,cur)))
#define XFS_BMAP_BLOCK_ISIZE(lev,cur) \
(((lev) == (cur)->bc_nlevels - 1 ? \
XFS_BMAP_RBLOCK_ISIZE(lev,cur) : XFS_BMAP_IBLOCK_SIZE(lev,cur)))
#define XFS_BMAP_BLOCK_DMAXRECS(lev,cur) \
(((lev) == (cur)->bc_nlevels - 1 ? \
XFS_BTREE_BLOCK_MAXRECS(XFS_BMAP_RBLOCK_DSIZE(lev,cur), \
xfs_bmdr, (lev) == 0) : \
((cur)->bc_mp->m_bmap_dmxr[(lev) != 0])))
#define XFS_BMAP_BLOCK_IMAXRECS(lev,cur) \
(((lev) == (cur)->bc_nlevels - 1 ? \
XFS_BTREE_BLOCK_MAXRECS(XFS_BMAP_RBLOCK_ISIZE(lev,cur),\
xfs_bmbt, (lev) == 0) : \
((cur)->bc_mp->m_bmap_dmxr[(lev) != 0])))
#define XFS_BMAP_BLOCK_DMINRECS(lev,cur) \
(((lev) == (cur)->bc_nlevels - 1 ? \
XFS_BTREE_BLOCK_MINRECS(XFS_BMAP_RBLOCK_DSIZE(lev,cur),\
xfs_bmdr, (lev) == 0) : \
((cur)->bc_mp->m_bmap_dmnr[(lev) != 0])))
#define XFS_BMAP_BLOCK_IMINRECS(lev,cur) \
(((lev) == (cur)->bc_nlevels - 1 ? \
XFS_BTREE_BLOCK_MINRECS(XFS_BMAP_RBLOCK_ISIZE(lev,cur),\
xfs_bmbt, (lev) == 0) : \
((cur)->bc_mp->m_bmap_dmnr[(lev) != 0])))
#define XFS_BMAP_REC_DADDR(bb,i,cur) \
(XFS_BTREE_REC_ADDR(XFS_BMAP_BLOCK_DSIZE( \
be16_to_cpu((bb)->bb_level), cur), \
xfs_bmbt, bb, i, XFS_BMAP_BLOCK_DMAXRECS( \
be16_to_cpu((bb)->bb_level), cur)))
#define XFS_BMAP_REC_IADDR(bb,i,cur) \
(XFS_BTREE_REC_ADDR(XFS_BMAP_BLOCK_ISIZE( \
be16_to_cpu((bb)->bb_level), cur), \
xfs_bmbt, bb, i, XFS_BMAP_BLOCK_IMAXRECS( \
be16_to_cpu((bb)->bb_level), cur)))
#define XFS_BMAP_KEY_DADDR(bb,i,cur) \
(XFS_BTREE_KEY_ADDR(XFS_BMAP_BLOCK_DSIZE( \
be16_to_cpu((bb)->bb_level), cur), \
xfs_bmbt, bb, i, XFS_BMAP_BLOCK_DMAXRECS( \
be16_to_cpu((bb)->bb_level), cur)))
#define XFS_BMAP_KEY_IADDR(bb,i,cur) \
(XFS_BTREE_KEY_ADDR(XFS_BMAP_BLOCK_ISIZE( \
be16_to_cpu((bb)->bb_level), cur), \
xfs_bmbt, bb, i, XFS_BMAP_BLOCK_IMAXRECS( \
be16_to_cpu((bb)->bb_level), cur)))
#define XFS_BMAP_PTR_DADDR(bb,i,cur) \
(XFS_BTREE_PTR_ADDR(XFS_BMAP_BLOCK_DSIZE( \
be16_to_cpu((bb)->bb_level), cur), \
xfs_bmbt, bb, i, XFS_BMAP_BLOCK_DMAXRECS( \
be16_to_cpu((bb)->bb_level), cur)))
#define XFS_BMAP_PTR_IADDR(bb,i,cur) \
(XFS_BTREE_PTR_ADDR(XFS_BMAP_BLOCK_ISIZE( \
be16_to_cpu((bb)->bb_level), cur), \
xfs_bmbt, bb, i, XFS_BMAP_BLOCK_IMAXRECS( \
be16_to_cpu((bb)->bb_level), cur)))
/*
* These are to be used when we know the size of the block and
* we don't have a cursor.
*/
#define XFS_BMAP_BROOT_REC_ADDR(bb,i,sz) \
(XFS_BTREE_REC_ADDR(sz,xfs_bmbt,bb,i,XFS_BMAP_BROOT_MAXRECS(sz)))
#define XFS_BMAP_BROOT_KEY_ADDR(bb,i,sz) \
(XFS_BTREE_KEY_ADDR(sz,xfs_bmbt,bb,i,XFS_BMAP_BROOT_MAXRECS(sz)))
#define XFS_BMAP_BROOT_PTR_ADDR(bb,i,sz) \
(XFS_BTREE_PTR_ADDR(sz,xfs_bmbt,bb,i,XFS_BMAP_BROOT_MAXRECS(sz)))
#define XFS_BMAP_BROOT_NUMRECS(bb) be16_to_cpu((bb)->bb_numrecs)
#define XFS_BMAP_BROOT_MAXRECS(sz) XFS_BTREE_BLOCK_MAXRECS(sz,xfs_bmbt,0)
#define XFS_BMAP_BROOT_SPACE_CALC(nrecs) \
(int)(sizeof(xfs_bmbt_block_t) + \
((nrecs) * (sizeof(xfs_bmbt_key_t) + sizeof(xfs_bmbt_ptr_t))))
#define XFS_BMAP_BROOT_SPACE(bb) \
(XFS_BMAP_BROOT_SPACE_CALC(be16_to_cpu((bb)->bb_numrecs)))
#define XFS_BMDR_SPACE_CALC(nrecs) \
(int)(sizeof(xfs_bmdr_block_t) + \
((nrecs) * (sizeof(xfs_bmbt_key_t) + sizeof(xfs_bmbt_ptr_t))))
/*
* Maximum number of bmap btree levels.
*/
#define XFS_BM_MAXLEVELS(mp,w) ((mp)->m_bm_maxlevels[(w)])
#define XFS_BMAP_SANITY_CHECK(mp,bb,level) \
(be32_to_cpu((bb)->bb_magic) == XFS_BMAP_MAGIC && \
be16_to_cpu((bb)->bb_level) == level && \
be16_to_cpu((bb)->bb_numrecs) > 0 && \
be16_to_cpu((bb)->bb_numrecs) <= (mp)->m_bmap_dmxr[(level) != 0])
#ifdef __KERNEL__
#if defined(XFS_BMBT_TRACE)
/*
* Trace buffer entry types.
*/
#define XFS_BMBT_KTRACE_ARGBI 1
#define XFS_BMBT_KTRACE_ARGBII 2
#define XFS_BMBT_KTRACE_ARGFFFI 3
#define XFS_BMBT_KTRACE_ARGI 4
#define XFS_BMBT_KTRACE_ARGIFK 5
#define XFS_BMBT_KTRACE_ARGIFR 6
#define XFS_BMBT_KTRACE_ARGIK 7
#define XFS_BMBT_KTRACE_CUR 8
#define XFS_BMBT_TRACE_SIZE 4096 /* size of global trace buffer */
#define XFS_BMBT_KTRACE_SIZE 32 /* size of per-inode trace buffer */
extern ktrace_t *xfs_bmbt_trace_buf;
#endif
/*
* Prototypes for xfs_bmap.c to call.
*/
extern void xfs_bmdr_to_bmbt(xfs_bmdr_block_t *, int, xfs_bmbt_block_t *, int);
extern int xfs_bmbt_decrement(struct xfs_btree_cur *, int, int *);
extern int xfs_bmbt_delete(struct xfs_btree_cur *, int *);
extern void xfs_bmbt_get_all(xfs_bmbt_rec_t *r, xfs_bmbt_irec_t *s);
extern xfs_bmbt_block_t *xfs_bmbt_get_block(struct xfs_btree_cur *cur,
int, struct xfs_buf **bpp);
extern xfs_filblks_t xfs_bmbt_get_blockcount(xfs_bmbt_rec_t *r);
extern xfs_fsblock_t xfs_bmbt_get_startblock(xfs_bmbt_rec_t *r);
extern xfs_fileoff_t xfs_bmbt_get_startoff(xfs_bmbt_rec_t *r);
extern xfs_exntst_t xfs_bmbt_get_state(xfs_bmbt_rec_t *r);
#ifndef XFS_NATIVE_HOST
extern void xfs_bmbt_disk_get_all(xfs_bmbt_rec_t *r, xfs_bmbt_irec_t *s);
extern xfs_exntst_t xfs_bmbt_disk_get_state(xfs_bmbt_rec_t *r);
extern xfs_filblks_t xfs_bmbt_disk_get_blockcount(xfs_bmbt_rec_t *r);
extern xfs_fsblock_t xfs_bmbt_disk_get_startblock(xfs_bmbt_rec_t *r);
extern xfs_fileoff_t xfs_bmbt_disk_get_startoff(xfs_bmbt_rec_t *r);
#else
#define xfs_bmbt_disk_get_all(r, s) xfs_bmbt_get_all(r, s)
#define xfs_bmbt_disk_get_state(r) xfs_bmbt_get_state(r)
#define xfs_bmbt_disk_get_blockcount(r) xfs_bmbt_get_blockcount(r)
#define xfs_bmbt_disk_get_startblock(r) xfs_bmbt_get_blockcount(r)
#define xfs_bmbt_disk_get_startoff(r) xfs_bmbt_get_startoff(r)
#endif /* XFS_NATIVE_HOST */
extern int xfs_bmbt_increment(struct xfs_btree_cur *, int, int *);
extern int xfs_bmbt_insert(struct xfs_btree_cur *, int *);
extern void xfs_bmbt_log_block(struct xfs_btree_cur *, struct xfs_buf *, int);
extern void xfs_bmbt_log_recs(struct xfs_btree_cur *, struct xfs_buf *, int,
int);
extern int xfs_bmbt_lookup_eq(struct xfs_btree_cur *, xfs_fileoff_t,
xfs_fsblock_t, xfs_filblks_t, int *);
extern int xfs_bmbt_lookup_ge(struct xfs_btree_cur *, xfs_fileoff_t,
xfs_fsblock_t, xfs_filblks_t, int *);
/*
* Give the bmap btree a new root block. Copy the old broot contents
* down into a real block and make the broot point to it.
*/
extern int xfs_bmbt_newroot(struct xfs_btree_cur *cur, int *lflags, int *stat);
extern void xfs_bmbt_set_all(xfs_bmbt_rec_t *r, xfs_bmbt_irec_t *s);
extern void xfs_bmbt_set_allf(xfs_bmbt_rec_t *r, xfs_fileoff_t o,
xfs_fsblock_t b, xfs_filblks_t c, xfs_exntst_t v);
extern void xfs_bmbt_set_blockcount(xfs_bmbt_rec_t *r, xfs_filblks_t v);
extern void xfs_bmbt_set_startblock(xfs_bmbt_rec_t *r, xfs_fsblock_t v);
extern void xfs_bmbt_set_startoff(xfs_bmbt_rec_t *r, xfs_fileoff_t v);
extern void xfs_bmbt_set_state(xfs_bmbt_rec_t *r, xfs_exntst_t v);
#ifndef XFS_NATIVE_HOST
extern void xfs_bmbt_disk_set_all(xfs_bmbt_rec_t *r, xfs_bmbt_irec_t *s);
extern void xfs_bmbt_disk_set_allf(xfs_bmbt_rec_t *r, xfs_fileoff_t o,
xfs_fsblock_t b, xfs_filblks_t c, xfs_exntst_t v);
#else
#define xfs_bmbt_disk_set_all(r, s) xfs_bmbt_set_all(r, s)
#define xfs_bmbt_disk_set_allf(r, o, b, c, v) xfs_bmbt_set_allf(r, o, b, c, v)
#endif /* XFS_NATIVE_HOST */
extern void xfs_bmbt_to_bmdr(xfs_bmbt_block_t *, int, xfs_bmdr_block_t *, int);
extern int xfs_bmbt_update(struct xfs_btree_cur *, xfs_fileoff_t,
xfs_fsblock_t, xfs_filblks_t, xfs_exntst_t);
#ifdef DEBUG
/*
* Get the data from the pointed-to record.
*/
extern int xfs_bmbt_get_rec(struct xfs_btree_cur *, xfs_fileoff_t *,
xfs_fsblock_t *, xfs_filblks_t *,
xfs_exntst_t *, int *);
#endif
#endif /* __KERNEL__ */
#endif /* __XFS_BMAP_BTREE_H__ */

View File

@ -1,943 +0,0 @@
/*
* Copyright (c) 2000-2002,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"
#include "xfs_fs.h"
#include "xfs_types.h"
#include "xfs_bit.h"
#include "xfs_log.h"
#include "xfs_inum.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_bmap_btree.h"
#include "xfs_alloc_btree.h"
#include "xfs_ialloc_btree.h"
#include "xfs_dir_sf.h"
#include "xfs_dir2_sf.h"
#include "xfs_attr_sf.h"
#include "xfs_dinode.h"
#include "xfs_inode.h"
#include "xfs_btree.h"
#include "xfs_ialloc.h"
#include "xfs_error.h"
/*
* Cursor allocation zone.
*/
kmem_zone_t *xfs_btree_cur_zone;
/*
* Btree magic numbers.
*/
const __uint32_t xfs_magics[XFS_BTNUM_MAX] =
{
XFS_ABTB_MAGIC, XFS_ABTC_MAGIC, XFS_BMAP_MAGIC, XFS_IBT_MAGIC
};
/*
* Prototypes for internal routines.
*/
/*
* Checking routine: return maxrecs for the block.
*/
STATIC int /* number of records fitting in block */
xfs_btree_maxrecs(
xfs_btree_cur_t *cur, /* btree cursor */
xfs_btree_block_t *block);/* generic btree block pointer */
/*
* Internal routines.
*/
/*
* Retrieve the block pointer from the cursor at the given level.
* This may be a bmap btree root or from a buffer.
*/
STATIC xfs_btree_block_t * /* generic btree block pointer */
xfs_btree_get_block(
xfs_btree_cur_t *cur, /* btree cursor */
int level, /* level in btree */
struct xfs_buf **bpp); /* buffer containing the block */
/*
* Checking routine: return maxrecs for the block.
*/
STATIC int /* number of records fitting in block */
xfs_btree_maxrecs(
xfs_btree_cur_t *cur, /* btree cursor */
xfs_btree_block_t *block) /* generic btree block pointer */
{
switch (cur->bc_btnum) {
case XFS_BTNUM_BNO:
case XFS_BTNUM_CNT:
return (int)XFS_ALLOC_BLOCK_MAXRECS(
be16_to_cpu(block->bb_h.bb_level), cur);
case XFS_BTNUM_BMAP:
return (int)XFS_BMAP_BLOCK_IMAXRECS(
be16_to_cpu(block->bb_h.bb_level), cur);
case XFS_BTNUM_INO:
return (int)XFS_INOBT_BLOCK_MAXRECS(
be16_to_cpu(block->bb_h.bb_level), cur);
default:
ASSERT(0);
return 0;
}
}
/*
* External routines.
*/
#ifdef DEBUG
/*
* Debug routine: check that block header is ok.
*/
void
xfs_btree_check_block(
xfs_btree_cur_t *cur, /* btree cursor */
xfs_btree_block_t *block, /* generic btree block pointer */
int level, /* level of the btree block */
xfs_buf_t *bp) /* buffer containing block, if any */
{
if (XFS_BTREE_LONG_PTRS(cur->bc_btnum))
xfs_btree_check_lblock(cur, (xfs_btree_lblock_t *)block, level,
bp);
else
xfs_btree_check_sblock(cur, (xfs_btree_sblock_t *)block, level,
bp);
}
/*
* Debug routine: check that keys are in the right order.
*/
void
xfs_btree_check_key(
xfs_btnum_t btnum, /* btree identifier */
void *ak1, /* pointer to left (lower) key */
void *ak2) /* pointer to right (higher) key */
{
switch (btnum) {
case XFS_BTNUM_BNO: {
xfs_alloc_key_t *k1;
xfs_alloc_key_t *k2;
k1 = ak1;
k2 = ak2;
ASSERT(be32_to_cpu(k1->ar_startblock) < be32_to_cpu(k2->ar_startblock));
break;
}
case XFS_BTNUM_CNT: {
xfs_alloc_key_t *k1;
xfs_alloc_key_t *k2;
k1 = ak1;
k2 = ak2;
ASSERT(be32_to_cpu(k1->ar_blockcount) < be32_to_cpu(k2->ar_blockcount) ||
(k1->ar_blockcount == k2->ar_blockcount &&
be32_to_cpu(k1->ar_startblock) < be32_to_cpu(k2->ar_startblock)));
break;
}
case XFS_BTNUM_BMAP: {
xfs_bmbt_key_t *k1;
xfs_bmbt_key_t *k2;
k1 = ak1;
k2 = ak2;
ASSERT(INT_GET(k1->br_startoff, ARCH_CONVERT) < INT_GET(k2->br_startoff, ARCH_CONVERT));
break;
}
case XFS_BTNUM_INO: {
xfs_inobt_key_t *k1;
xfs_inobt_key_t *k2;
k1 = ak1;
k2 = ak2;
ASSERT(INT_GET(k1->ir_startino, ARCH_CONVERT) < INT_GET(k2->ir_startino, ARCH_CONVERT));
break;
}
default:
ASSERT(0);
}
}
#endif /* DEBUG */
/*
* Checking routine: check that long form block header is ok.
*/
/* ARGSUSED */
int /* error (0 or EFSCORRUPTED) */
xfs_btree_check_lblock(
xfs_btree_cur_t *cur, /* btree cursor */
xfs_btree_lblock_t *block, /* btree long form block pointer */
int level, /* level of the btree block */
xfs_buf_t *bp) /* buffer for block, if any */
{
int lblock_ok; /* block passes checks */
xfs_mount_t *mp; /* file system mount point */
mp = cur->bc_mp;
lblock_ok =
be32_to_cpu(block->bb_magic) == xfs_magics[cur->bc_btnum] &&
be16_to_cpu(block->bb_level) == level &&
be16_to_cpu(block->bb_numrecs) <=
xfs_btree_maxrecs(cur, (xfs_btree_block_t *)block) &&
block->bb_leftsib &&
(be64_to_cpu(block->bb_leftsib) == NULLDFSBNO ||
XFS_FSB_SANITY_CHECK(mp, be64_to_cpu(block->bb_leftsib))) &&
block->bb_rightsib &&
(be64_to_cpu(block->bb_rightsib) == NULLDFSBNO ||
XFS_FSB_SANITY_CHECK(mp, be64_to_cpu(block->bb_rightsib)));
if (unlikely(XFS_TEST_ERROR(!lblock_ok, mp, XFS_ERRTAG_BTREE_CHECK_LBLOCK,
XFS_RANDOM_BTREE_CHECK_LBLOCK))) {
if (bp)
xfs_buftrace("LBTREE ERROR", bp);
XFS_ERROR_REPORT("xfs_btree_check_lblock", XFS_ERRLEVEL_LOW,
mp);
return XFS_ERROR(EFSCORRUPTED);
}
return 0;
}
/*
* Checking routine: check that (long) pointer is ok.
*/
int /* error (0 or EFSCORRUPTED) */
xfs_btree_check_lptr(
xfs_btree_cur_t *cur, /* btree cursor */
xfs_dfsbno_t ptr, /* btree block disk address */
int level) /* btree block level */
{
xfs_mount_t *mp; /* file system mount point */
mp = cur->bc_mp;
XFS_WANT_CORRUPTED_RETURN(
level > 0 &&
ptr != NULLDFSBNO &&
XFS_FSB_SANITY_CHECK(mp, ptr));
return 0;
}
#ifdef DEBUG
/*
* Debug routine: check that records are in the right order.
*/
void
xfs_btree_check_rec(
xfs_btnum_t btnum, /* btree identifier */
void *ar1, /* pointer to left (lower) record */
void *ar2) /* pointer to right (higher) record */
{
switch (btnum) {
case XFS_BTNUM_BNO: {
xfs_alloc_rec_t *r1;
xfs_alloc_rec_t *r2;
r1 = ar1;
r2 = ar2;
ASSERT(be32_to_cpu(r1->ar_startblock) +
be32_to_cpu(r1->ar_blockcount) <=
be32_to_cpu(r2->ar_startblock));
break;
}
case XFS_BTNUM_CNT: {
xfs_alloc_rec_t *r1;
xfs_alloc_rec_t *r2;
r1 = ar1;
r2 = ar2;
ASSERT(be32_to_cpu(r1->ar_blockcount) < be32_to_cpu(r2->ar_blockcount) ||
(r1->ar_blockcount == r2->ar_blockcount &&
be32_to_cpu(r1->ar_startblock) < be32_to_cpu(r2->ar_startblock)));
break;
}
case XFS_BTNUM_BMAP: {
xfs_bmbt_rec_t *r1;
xfs_bmbt_rec_t *r2;
r1 = ar1;
r2 = ar2;
ASSERT(xfs_bmbt_disk_get_startoff(r1) +
xfs_bmbt_disk_get_blockcount(r1) <=
xfs_bmbt_disk_get_startoff(r2));
break;
}
case XFS_BTNUM_INO: {
xfs_inobt_rec_t *r1;
xfs_inobt_rec_t *r2;
r1 = ar1;
r2 = ar2;
ASSERT(INT_GET(r1->ir_startino, ARCH_CONVERT) + XFS_INODES_PER_CHUNK <=
INT_GET(r2->ir_startino, ARCH_CONVERT));
break;
}
default:
ASSERT(0);
}
}
#endif /* DEBUG */
/*
* Checking routine: check that block header is ok.
*/
/* ARGSUSED */
int /* error (0 or EFSCORRUPTED) */
xfs_btree_check_sblock(
xfs_btree_cur_t *cur, /* btree cursor */
xfs_btree_sblock_t *block, /* btree short form block pointer */
int level, /* level of the btree block */
xfs_buf_t *bp) /* buffer containing block */
{
xfs_buf_t *agbp; /* buffer for ag. freespace struct */
xfs_agf_t *agf; /* ag. freespace structure */
xfs_agblock_t agflen; /* native ag. freespace length */
int sblock_ok; /* block passes checks */
agbp = cur->bc_private.a.agbp;
agf = XFS_BUF_TO_AGF(agbp);
agflen = be32_to_cpu(agf->agf_length);
sblock_ok =
be32_to_cpu(block->bb_magic) == xfs_magics[cur->bc_btnum] &&
be16_to_cpu(block->bb_level) == level &&
be16_to_cpu(block->bb_numrecs) <=
xfs_btree_maxrecs(cur, (xfs_btree_block_t *)block) &&
(be32_to_cpu(block->bb_leftsib) == NULLAGBLOCK ||
be32_to_cpu(block->bb_leftsib) < agflen) &&
block->bb_leftsib &&
(be32_to_cpu(block->bb_rightsib) == NULLAGBLOCK ||
be32_to_cpu(block->bb_rightsib) < agflen) &&
block->bb_rightsib;
if (unlikely(XFS_TEST_ERROR(!sblock_ok, cur->bc_mp,
XFS_ERRTAG_BTREE_CHECK_SBLOCK,
XFS_RANDOM_BTREE_CHECK_SBLOCK))) {
if (bp)
xfs_buftrace("SBTREE ERROR", bp);
XFS_ERROR_REPORT("xfs_btree_check_sblock", XFS_ERRLEVEL_LOW,
cur->bc_mp);
return XFS_ERROR(EFSCORRUPTED);
}
return 0;
}
/*
* Checking routine: check that (short) pointer is ok.
*/
int /* error (0 or EFSCORRUPTED) */
xfs_btree_check_sptr(
xfs_btree_cur_t *cur, /* btree cursor */
xfs_agblock_t ptr, /* btree block disk address */
int level) /* btree block level */
{
xfs_buf_t *agbp; /* buffer for ag. freespace struct */
xfs_agf_t *agf; /* ag. freespace structure */
agbp = cur->bc_private.a.agbp;
agf = XFS_BUF_TO_AGF(agbp);
XFS_WANT_CORRUPTED_RETURN(
level > 0 &&
ptr != NULLAGBLOCK && ptr != 0 &&
ptr < be32_to_cpu(agf->agf_length));
return 0;
}
/*
* Delete the btree cursor.
*/
void
xfs_btree_del_cursor(
xfs_btree_cur_t *cur, /* btree cursor */
int error) /* del because of error */
{
int i; /* btree level */
/*
* Clear the buffer pointers, and release the buffers.
* If we're doing this in the face of an error, we
* need to make sure to inspect all of the entries
* in the bc_bufs array for buffers to be unlocked.
* This is because some of the btree code works from
* level n down to 0, and if we get an error along
* the way we won't have initialized all the entries
* down to 0.
*/
for (i = 0; i < cur->bc_nlevels; i++) {
if (cur->bc_bufs[i])
xfs_btree_setbuf(cur, i, NULL);
else if (!error)
break;
}
/*
* Can't free a bmap cursor without having dealt with the
* allocated indirect blocks' accounting.
*/
ASSERT(cur->bc_btnum != XFS_BTNUM_BMAP ||
cur->bc_private.b.allocated == 0);
/*
* Free the cursor.
*/
kmem_zone_free(xfs_btree_cur_zone, cur);
}
/*
* Duplicate the btree cursor.
* Allocate a new one, copy the record, re-get the buffers.
*/
int /* error */
xfs_btree_dup_cursor(
xfs_btree_cur_t *cur, /* input cursor */
xfs_btree_cur_t **ncur) /* output cursor */
{
xfs_buf_t *bp; /* btree block's buffer pointer */
int error; /* error return value */
int i; /* level number of btree block */
xfs_mount_t *mp; /* mount structure for filesystem */
xfs_btree_cur_t *new; /* new cursor value */
xfs_trans_t *tp; /* transaction pointer, can be NULL */
tp = cur->bc_tp;
mp = cur->bc_mp;
/*
* Allocate a new cursor like the old one.
*/
new = xfs_btree_init_cursor(mp, tp, cur->bc_private.a.agbp,
cur->bc_private.a.agno, cur->bc_btnum, cur->bc_private.b.ip,
cur->bc_private.b.whichfork);
/*
* Copy the record currently in the cursor.
*/
new->bc_rec = cur->bc_rec;
/*
* For each level current, re-get the buffer and copy the ptr value.
*/
for (i = 0; i < new->bc_nlevels; i++) {
new->bc_ptrs[i] = cur->bc_ptrs[i];
new->bc_ra[i] = cur->bc_ra[i];
if ((bp = cur->bc_bufs[i])) {
if ((error = xfs_trans_read_buf(mp, tp, mp->m_ddev_targp,
XFS_BUF_ADDR(bp), mp->m_bsize, 0, &bp))) {
xfs_btree_del_cursor(new, error);
*ncur = NULL;
return error;
}
new->bc_bufs[i] = bp;
ASSERT(bp);
ASSERT(!XFS_BUF_GETERROR(bp));
} else
new->bc_bufs[i] = NULL;
}
/*
* For bmap btrees, copy the firstblock, flist, and flags values,
* since init cursor doesn't get them.
*/
if (new->bc_btnum == XFS_BTNUM_BMAP) {
new->bc_private.b.firstblock = cur->bc_private.b.firstblock;
new->bc_private.b.flist = cur->bc_private.b.flist;
new->bc_private.b.flags = cur->bc_private.b.flags;
}
*ncur = new;
return 0;
}
/*
* Change the cursor to point to the first record at the given level.
* Other levels are unaffected.
*/
int /* success=1, failure=0 */
xfs_btree_firstrec(
xfs_btree_cur_t *cur, /* btree cursor */
int level) /* level to change */
{
xfs_btree_block_t *block; /* generic btree block pointer */
xfs_buf_t *bp; /* buffer containing block */
/*
* Get the block pointer for this level.
*/
block = xfs_btree_get_block(cur, level, &bp);
xfs_btree_check_block(cur, block, level, bp);
/*
* It's empty, there is no such record.
*/
if (!block->bb_h.bb_numrecs)
return 0;
/*
* Set the ptr value to 1, that's the first record/key.
*/
cur->bc_ptrs[level] = 1;
return 1;
}
/*
* Retrieve the block pointer from the cursor at the given level.
* This may be a bmap btree root or from a buffer.
*/
STATIC xfs_btree_block_t * /* generic btree block pointer */
xfs_btree_get_block(
xfs_btree_cur_t *cur, /* btree cursor */
int level, /* level in btree */
xfs_buf_t **bpp) /* buffer containing the block */
{
xfs_btree_block_t *block; /* return value */
xfs_buf_t *bp; /* return buffer */
xfs_ifork_t *ifp; /* inode fork pointer */
int whichfork; /* data or attr fork */
if (cur->bc_btnum == XFS_BTNUM_BMAP && level == cur->bc_nlevels - 1) {
whichfork = cur->bc_private.b.whichfork;
ifp = XFS_IFORK_PTR(cur->bc_private.b.ip, whichfork);
block = (xfs_btree_block_t *)ifp->if_broot;
bp = NULL;
} else {
bp = cur->bc_bufs[level];
block = XFS_BUF_TO_BLOCK(bp);
}
ASSERT(block != NULL);
*bpp = bp;
return block;
}
/*
* Get a buffer for the block, return it with no data read.
* Long-form addressing.
*/
xfs_buf_t * /* buffer for fsbno */
xfs_btree_get_bufl(
xfs_mount_t *mp, /* file system mount point */
xfs_trans_t *tp, /* transaction pointer */
xfs_fsblock_t fsbno, /* file system block number */
uint lock) /* lock flags for get_buf */
{
xfs_buf_t *bp; /* buffer pointer (return value) */
xfs_daddr_t d; /* real disk block address */
ASSERT(fsbno != NULLFSBLOCK);
d = XFS_FSB_TO_DADDR(mp, fsbno);
bp = xfs_trans_get_buf(tp, mp->m_ddev_targp, d, mp->m_bsize, lock);
ASSERT(bp);
ASSERT(!XFS_BUF_GETERROR(bp));
return bp;
}
/*
* Get a buffer for the block, return it with no data read.
* Short-form addressing.
*/
xfs_buf_t * /* buffer for agno/agbno */
xfs_btree_get_bufs(
xfs_mount_t *mp, /* file system mount point */
xfs_trans_t *tp, /* transaction pointer */
xfs_agnumber_t agno, /* allocation group number */
xfs_agblock_t agbno, /* allocation group block number */
uint lock) /* lock flags for get_buf */
{
xfs_buf_t *bp; /* buffer pointer (return value) */
xfs_daddr_t d; /* real disk block address */
ASSERT(agno != NULLAGNUMBER);
ASSERT(agbno != NULLAGBLOCK);
d = XFS_AGB_TO_DADDR(mp, agno, agbno);
bp = xfs_trans_get_buf(tp, mp->m_ddev_targp, d, mp->m_bsize, lock);
ASSERT(bp);
ASSERT(!XFS_BUF_GETERROR(bp));
return bp;
}
/*
* Allocate a new btree cursor.
* The cursor is either for allocation (A) or bmap (B) or inodes (I).
*/
xfs_btree_cur_t * /* new btree cursor */
xfs_btree_init_cursor(
xfs_mount_t *mp, /* file system mount point */
xfs_trans_t *tp, /* transaction pointer */
xfs_buf_t *agbp, /* (A only) buffer for agf structure */
/* (I only) buffer for agi structure */
xfs_agnumber_t agno, /* (AI only) allocation group number */
xfs_btnum_t btnum, /* btree identifier */
xfs_inode_t *ip, /* (B only) inode owning the btree */
int whichfork) /* (B only) data or attr fork */
{
xfs_agf_t *agf; /* (A) allocation group freespace */
xfs_agi_t *agi; /* (I) allocation group inodespace */
xfs_btree_cur_t *cur; /* return value */
xfs_ifork_t *ifp; /* (I) inode fork pointer */
int nlevels=0; /* number of levels in the btree */
ASSERT(xfs_btree_cur_zone != NULL);
/*
* Allocate a new cursor.
*/
cur = kmem_zone_zalloc(xfs_btree_cur_zone, KM_SLEEP);
/*
* Deduce the number of btree levels from the arguments.
*/
switch (btnum) {
case XFS_BTNUM_BNO:
case XFS_BTNUM_CNT:
agf = XFS_BUF_TO_AGF(agbp);
nlevels = be32_to_cpu(agf->agf_levels[btnum]);
break;
case XFS_BTNUM_BMAP:
ifp = XFS_IFORK_PTR(ip, whichfork);
nlevels = be16_to_cpu(ifp->if_broot->bb_level) + 1;
break;
case XFS_BTNUM_INO:
agi = XFS_BUF_TO_AGI(agbp);
nlevels = be32_to_cpu(agi->agi_level);
break;
default:
ASSERT(0);
}
/*
* Fill in the common fields.
*/
cur->bc_tp = tp;
cur->bc_mp = mp;
cur->bc_nlevels = nlevels;
cur->bc_btnum = btnum;
cur->bc_blocklog = mp->m_sb.sb_blocklog;
/*
* Fill in private fields.
*/
switch (btnum) {
case XFS_BTNUM_BNO:
case XFS_BTNUM_CNT:
/*
* Allocation btree fields.
*/
cur->bc_private.a.agbp = agbp;
cur->bc_private.a.agno = agno;
break;
case XFS_BTNUM_BMAP:
/*
* Bmap btree fields.
*/
cur->bc_private.b.forksize = XFS_IFORK_SIZE(ip, whichfork);
cur->bc_private.b.ip = ip;
cur->bc_private.b.firstblock = NULLFSBLOCK;
cur->bc_private.b.flist = NULL;
cur->bc_private.b.allocated = 0;
cur->bc_private.b.flags = 0;
cur->bc_private.b.whichfork = whichfork;
break;
case XFS_BTNUM_INO:
/*
* Inode allocation btree fields.
*/
cur->bc_private.i.agbp = agbp;
cur->bc_private.i.agno = agno;
break;
default:
ASSERT(0);
}
return cur;
}
/*
* Check for the cursor referring to the last block at the given level.
*/
int /* 1=is last block, 0=not last block */
xfs_btree_islastblock(
xfs_btree_cur_t *cur, /* btree cursor */
int level) /* level to check */
{
xfs_btree_block_t *block; /* generic btree block pointer */
xfs_buf_t *bp; /* buffer containing block */
block = xfs_btree_get_block(cur, level, &bp);
xfs_btree_check_block(cur, block, level, bp);
if (XFS_BTREE_LONG_PTRS(cur->bc_btnum))
return be64_to_cpu(block->bb_u.l.bb_rightsib) == NULLDFSBNO;
else
return be32_to_cpu(block->bb_u.s.bb_rightsib) == NULLAGBLOCK;
}
/*
* Change the cursor to point to the last record in the current block
* at the given level. Other levels are unaffected.
*/
int /* success=1, failure=0 */
xfs_btree_lastrec(
xfs_btree_cur_t *cur, /* btree cursor */
int level) /* level to change */
{
xfs_btree_block_t *block; /* generic btree block pointer */
xfs_buf_t *bp; /* buffer containing block */
/*
* Get the block pointer for this level.
*/
block = xfs_btree_get_block(cur, level, &bp);
xfs_btree_check_block(cur, block, level, bp);
/*
* It's empty, there is no such record.
*/
if (!block->bb_h.bb_numrecs)
return 0;
/*
* Set the ptr value to numrecs, that's the last record/key.
*/
cur->bc_ptrs[level] = be16_to_cpu(block->bb_h.bb_numrecs);
return 1;
}
/*
* Compute first and last byte offsets for the fields given.
* Interprets the offsets table, which contains struct field offsets.
*/
void
xfs_btree_offsets(
__int64_t fields, /* bitmask of fields */
const short *offsets, /* table of field offsets */
int nbits, /* number of bits to inspect */
int *first, /* output: first byte offset */
int *last) /* output: last byte offset */
{
int i; /* current bit number */
__int64_t imask; /* mask for current bit number */
ASSERT(fields != 0);
/*
* Find the lowest bit, so the first byte offset.
*/
for (i = 0, imask = 1LL; ; i++, imask <<= 1) {
if (imask & fields) {
*first = offsets[i];
break;
}
}
/*
* Find the highest bit, so the last byte offset.
*/
for (i = nbits - 1, imask = 1LL << i; ; i--, imask >>= 1) {
if (imask & fields) {
*last = offsets[i + 1] - 1;
break;
}
}
}
/*
* Get a buffer for the block, return it read in.
* Long-form addressing.
*/
int /* error */
xfs_btree_read_bufl(
xfs_mount_t *mp, /* file system mount point */
xfs_trans_t *tp, /* transaction pointer */
xfs_fsblock_t fsbno, /* file system block number */
uint lock, /* lock flags for read_buf */
xfs_buf_t **bpp, /* buffer for fsbno */
int refval) /* ref count value for buffer */
{
xfs_buf_t *bp; /* return value */
xfs_daddr_t d; /* real disk block address */
int error;
ASSERT(fsbno != NULLFSBLOCK);
d = XFS_FSB_TO_DADDR(mp, fsbno);
if ((error = xfs_trans_read_buf(mp, tp, mp->m_ddev_targp, d,
mp->m_bsize, lock, &bp))) {
return error;
}
ASSERT(!bp || !XFS_BUF_GETERROR(bp));
if (bp != NULL) {
XFS_BUF_SET_VTYPE_REF(bp, B_FS_MAP, refval);
}
*bpp = bp;
return 0;
}
/*
* Get a buffer for the block, return it read in.
* Short-form addressing.
*/
int /* error */
xfs_btree_read_bufs(
xfs_mount_t *mp, /* file system mount point */
xfs_trans_t *tp, /* transaction pointer */
xfs_agnumber_t agno, /* allocation group number */
xfs_agblock_t agbno, /* allocation group block number */
uint lock, /* lock flags for read_buf */
xfs_buf_t **bpp, /* buffer for agno/agbno */
int refval) /* ref count value for buffer */
{
xfs_buf_t *bp; /* return value */
xfs_daddr_t d; /* real disk block address */
int error;
ASSERT(agno != NULLAGNUMBER);
ASSERT(agbno != NULLAGBLOCK);
d = XFS_AGB_TO_DADDR(mp, agno, agbno);
if ((error = xfs_trans_read_buf(mp, tp, mp->m_ddev_targp, d,
mp->m_bsize, lock, &bp))) {
return error;
}
ASSERT(!bp || !XFS_BUF_GETERROR(bp));
if (bp != NULL) {
switch (refval) {
case XFS_ALLOC_BTREE_REF:
XFS_BUF_SET_VTYPE_REF(bp, B_FS_MAP, refval);
break;
case XFS_INO_BTREE_REF:
XFS_BUF_SET_VTYPE_REF(bp, B_FS_INOMAP, refval);
break;
}
}
*bpp = bp;
return 0;
}
/*
* Read-ahead the block, don't wait for it, don't return a buffer.
* Long-form addressing.
*/
/* ARGSUSED */
void
xfs_btree_reada_bufl(
xfs_mount_t *mp, /* file system mount point */
xfs_fsblock_t fsbno, /* file system block number */
xfs_extlen_t count) /* count of filesystem blocks */
{
xfs_daddr_t d;
ASSERT(fsbno != NULLFSBLOCK);
d = XFS_FSB_TO_DADDR(mp, fsbno);
xfs_baread(mp->m_ddev_targp, d, mp->m_bsize * count);
}
/*
* Read-ahead the block, don't wait for it, don't return a buffer.
* Short-form addressing.
*/
/* ARGSUSED */
void
xfs_btree_reada_bufs(
xfs_mount_t *mp, /* file system mount point */
xfs_agnumber_t agno, /* allocation group number */
xfs_agblock_t agbno, /* allocation group block number */
xfs_extlen_t count) /* count of filesystem blocks */
{
xfs_daddr_t d;
ASSERT(agno != NULLAGNUMBER);
ASSERT(agbno != NULLAGBLOCK);
d = XFS_AGB_TO_DADDR(mp, agno, agbno);
xfs_baread(mp->m_ddev_targp, d, mp->m_bsize * count);
}
/*
* Read-ahead btree blocks, at the given level.
* Bits in lr are set from XFS_BTCUR_{LEFT,RIGHT}RA.
*/
int
xfs_btree_readahead_core(
xfs_btree_cur_t *cur, /* btree cursor */
int lev, /* level in btree */
int lr) /* left/right bits */
{
xfs_alloc_block_t *a;
xfs_bmbt_block_t *b;
xfs_inobt_block_t *i;
int rval = 0;
ASSERT(cur->bc_bufs[lev] != NULL);
cur->bc_ra[lev] |= lr;
switch (cur->bc_btnum) {
case XFS_BTNUM_BNO:
case XFS_BTNUM_CNT:
a = XFS_BUF_TO_ALLOC_BLOCK(cur->bc_bufs[lev]);
if ((lr & XFS_BTCUR_LEFTRA) && be32_to_cpu(a->bb_leftsib) != NULLAGBLOCK) {
xfs_btree_reada_bufs(cur->bc_mp, cur->bc_private.a.agno,
be32_to_cpu(a->bb_leftsib), 1);
rval++;
}
if ((lr & XFS_BTCUR_RIGHTRA) && be32_to_cpu(a->bb_rightsib) != NULLAGBLOCK) {
xfs_btree_reada_bufs(cur->bc_mp, cur->bc_private.a.agno,
be32_to_cpu(a->bb_rightsib), 1);
rval++;
}
break;
case XFS_BTNUM_BMAP:
b = XFS_BUF_TO_BMBT_BLOCK(cur->bc_bufs[lev]);
if ((lr & XFS_BTCUR_LEFTRA) && be64_to_cpu(b->bb_leftsib) != NULLDFSBNO) {
xfs_btree_reada_bufl(cur->bc_mp, be64_to_cpu(b->bb_leftsib), 1);
rval++;
}
if ((lr & XFS_BTCUR_RIGHTRA) && be64_to_cpu(b->bb_rightsib) != NULLDFSBNO) {
xfs_btree_reada_bufl(cur->bc_mp, be64_to_cpu(b->bb_rightsib), 1);
rval++;
}
break;
case XFS_BTNUM_INO:
i = XFS_BUF_TO_INOBT_BLOCK(cur->bc_bufs[lev]);
if ((lr & XFS_BTCUR_LEFTRA) && be32_to_cpu(i->bb_leftsib) != NULLAGBLOCK) {
xfs_btree_reada_bufs(cur->bc_mp, cur->bc_private.i.agno,
be32_to_cpu(i->bb_leftsib), 1);
rval++;
}
if ((lr & XFS_BTCUR_RIGHTRA) && be32_to_cpu(i->bb_rightsib) != NULLAGBLOCK) {
xfs_btree_reada_bufs(cur->bc_mp, cur->bc_private.i.agno,
be32_to_cpu(i->bb_rightsib), 1);
rval++;
}
break;
default:
ASSERT(0);
}
return rval;
}
/*
* Set the buffer for level "lev" in the cursor to bp, releasing
* any previous buffer.
*/
void
xfs_btree_setbuf(
xfs_btree_cur_t *cur, /* btree cursor */
int lev, /* level in btree */
xfs_buf_t *bp) /* new buffer to set */
{
xfs_btree_block_t *b; /* btree block */
xfs_buf_t *obp; /* old buffer pointer */
obp = cur->bc_bufs[lev];
if (obp)
xfs_trans_brelse(cur->bc_tp, obp);
cur->bc_bufs[lev] = bp;
cur->bc_ra[lev] = 0;
if (!bp)
return;
b = XFS_BUF_TO_BLOCK(bp);
if (XFS_BTREE_LONG_PTRS(cur->bc_btnum)) {
if (be64_to_cpu(b->bb_u.l.bb_leftsib) == NULLDFSBNO)
cur->bc_ra[lev] |= XFS_BTCUR_LEFTRA;
if (be64_to_cpu(b->bb_u.l.bb_rightsib) == NULLDFSBNO)
cur->bc_ra[lev] |= XFS_BTCUR_RIGHTRA;
} else {
if (be32_to_cpu(b->bb_u.s.bb_leftsib) == NULLAGBLOCK)
cur->bc_ra[lev] |= XFS_BTCUR_LEFTRA;
if (be32_to_cpu(b->bb_u.s.bb_rightsib) == NULLAGBLOCK)
cur->bc_ra[lev] |= XFS_BTCUR_RIGHTRA;
}
}

View File

@ -1,473 +0,0 @@
/*
* Copyright (c) 2000-2001,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
*/
#ifndef __XFS_BTREE_H__
#define __XFS_BTREE_H__
struct xfs_buf;
struct xfs_bmap_free;
struct xfs_inode;
struct xfs_mount;
struct xfs_trans;
/*
* This nonsense is to make -wlint happy.
*/
#define XFS_LOOKUP_EQ ((xfs_lookup_t)XFS_LOOKUP_EQi)
#define XFS_LOOKUP_LE ((xfs_lookup_t)XFS_LOOKUP_LEi)
#define XFS_LOOKUP_GE ((xfs_lookup_t)XFS_LOOKUP_GEi)
#define XFS_BTNUM_BNO ((xfs_btnum_t)XFS_BTNUM_BNOi)
#define XFS_BTNUM_CNT ((xfs_btnum_t)XFS_BTNUM_CNTi)
#define XFS_BTNUM_BMAP ((xfs_btnum_t)XFS_BTNUM_BMAPi)
#define XFS_BTNUM_INO ((xfs_btnum_t)XFS_BTNUM_INOi)
/*
* Short form header: space allocation btrees.
*/
typedef struct xfs_btree_sblock {
__be32 bb_magic; /* magic number for block type */
__be16 bb_level; /* 0 is a leaf */
__be16 bb_numrecs; /* current # of data records */
__be32 bb_leftsib; /* left sibling block or NULLAGBLOCK */
__be32 bb_rightsib; /* right sibling block or NULLAGBLOCK */
} xfs_btree_sblock_t;
/*
* Long form header: bmap btrees.
*/
typedef struct xfs_btree_lblock {
__be32 bb_magic; /* magic number for block type */
__be16 bb_level; /* 0 is a leaf */
__be16 bb_numrecs; /* current # of data records */
__be64 bb_leftsib; /* left sibling block or NULLDFSBNO */
__be64 bb_rightsib; /* right sibling block or NULLDFSBNO */
} xfs_btree_lblock_t;
/*
* Combined header and structure, used by common code.
*/
typedef struct xfs_btree_hdr
{
__be32 bb_magic; /* magic number for block type */
__be16 bb_level; /* 0 is a leaf */
__be16 bb_numrecs; /* current # of data records */
} xfs_btree_hdr_t;
typedef struct xfs_btree_block {
xfs_btree_hdr_t bb_h; /* header */
union {
struct {
__be32 bb_leftsib;
__be32 bb_rightsib;
} s; /* short form pointers */
struct {
__be64 bb_leftsib;
__be64 bb_rightsib;
} l; /* long form pointers */
} bb_u; /* rest */
} xfs_btree_block_t;
/*
* For logging record fields.
*/
#define XFS_BB_MAGIC 0x01
#define XFS_BB_LEVEL 0x02
#define XFS_BB_NUMRECS 0x04
#define XFS_BB_LEFTSIB 0x08
#define XFS_BB_RIGHTSIB 0x10
#define XFS_BB_NUM_BITS 5
#define XFS_BB_ALL_BITS ((1 << XFS_BB_NUM_BITS) - 1)
/*
* Boolean to select which form of xfs_btree_block_t.bb_u to use.
*/
#define XFS_BTREE_LONG_PTRS(btnum) ((btnum) == XFS_BTNUM_BMAP)
/*
* Magic numbers for btree blocks.
*/
extern const __uint32_t xfs_magics[];
/*
* Maximum and minimum records in a btree block.
* Given block size, type prefix, and leaf flag (0 or 1).
* The divisor below is equivalent to lf ? (e1) : (e2) but that produces
* compiler warnings.
*/
#define XFS_BTREE_BLOCK_MAXRECS(bsz,t,lf) \
((int)(((bsz) - (uint)sizeof(t ## _block_t)) / \
(((lf) * (uint)sizeof(t ## _rec_t)) + \
((1 - (lf)) * \
((uint)sizeof(t ## _key_t) + (uint)sizeof(t ## _ptr_t))))))
#define XFS_BTREE_BLOCK_MINRECS(bsz,t,lf) \
(XFS_BTREE_BLOCK_MAXRECS(bsz,t,lf) / 2)
/*
* Record, key, and pointer address calculation macros.
* Given block size, type prefix, block pointer, and index of requested entry
* (first entry numbered 1).
*/
#define XFS_BTREE_REC_ADDR(bsz,t,bb,i,mxr) \
((t ## _rec_t *)((char *)(bb) + sizeof(t ## _block_t) + \
((i) - 1) * sizeof(t ## _rec_t)))
#define XFS_BTREE_KEY_ADDR(bsz,t,bb,i,mxr) \
((t ## _key_t *)((char *)(bb) + sizeof(t ## _block_t) + \
((i) - 1) * sizeof(t ## _key_t)))
#define XFS_BTREE_PTR_ADDR(bsz,t,bb,i,mxr) \
((t ## _ptr_t *)((char *)(bb) + sizeof(t ## _block_t) + \
(mxr) * sizeof(t ## _key_t) + ((i) - 1) * sizeof(t ## _ptr_t)))
#define XFS_BTREE_MAXLEVELS 8 /* max of all btrees */
/*
* Btree cursor structure.
* This collects all information needed by the btree code in one place.
*/
typedef struct xfs_btree_cur
{
struct xfs_trans *bc_tp; /* transaction we're in, if any */
struct xfs_mount *bc_mp; /* file system mount struct */
union {
xfs_alloc_rec_incore_t a;
xfs_bmbt_irec_t b;
xfs_inobt_rec_t i;
} bc_rec; /* current insert/search record value */
struct xfs_buf *bc_bufs[XFS_BTREE_MAXLEVELS]; /* buf ptr per level */
int bc_ptrs[XFS_BTREE_MAXLEVELS]; /* key/record # */
__uint8_t bc_ra[XFS_BTREE_MAXLEVELS]; /* readahead bits */
#define XFS_BTCUR_LEFTRA 1 /* left sibling has been read-ahead */
#define XFS_BTCUR_RIGHTRA 2 /* right sibling has been read-ahead */
__uint8_t bc_nlevels; /* number of levels in the tree */
__uint8_t bc_blocklog; /* log2(blocksize) of btree blocks */
xfs_btnum_t bc_btnum; /* identifies which btree type */
union {
struct { /* needed for BNO, CNT */
struct xfs_buf *agbp; /* agf buffer pointer */
xfs_agnumber_t agno; /* ag number */
} a;
struct { /* needed for BMAP */
struct xfs_inode *ip; /* pointer to our inode */
struct xfs_bmap_free *flist; /* list to free after */
xfs_fsblock_t firstblock; /* 1st blk allocated */
int allocated; /* count of alloced */
short forksize; /* fork's inode space */
char whichfork; /* data or attr fork */
char flags; /* flags */
#define XFS_BTCUR_BPRV_WASDEL 1 /* was delayed */
} b;
struct { /* needed for INO */
struct xfs_buf *agbp; /* agi buffer pointer */
xfs_agnumber_t agno; /* ag number */
} i;
} bc_private; /* per-btree type data */
} xfs_btree_cur_t;
#define XFS_BTREE_NOERROR 0
#define XFS_BTREE_ERROR 1
/*
* Convert from buffer to btree block header.
*/
#define XFS_BUF_TO_BLOCK(bp) ((xfs_btree_block_t *)XFS_BUF_PTR(bp))
#define XFS_BUF_TO_LBLOCK(bp) ((xfs_btree_lblock_t *)XFS_BUF_PTR(bp))
#define XFS_BUF_TO_SBLOCK(bp) ((xfs_btree_sblock_t *)XFS_BUF_PTR(bp))
#ifdef __KERNEL__
#ifdef DEBUG
/*
* Debug routine: check that block header is ok.
*/
void
xfs_btree_check_block(
xfs_btree_cur_t *cur, /* btree cursor */
xfs_btree_block_t *block, /* generic btree block pointer */
int level, /* level of the btree block */
struct xfs_buf *bp); /* buffer containing block, if any */
/*
* Debug routine: check that keys are in the right order.
*/
void
xfs_btree_check_key(
xfs_btnum_t btnum, /* btree identifier */
void *ak1, /* pointer to left (lower) key */
void *ak2); /* pointer to right (higher) key */
/*
* Debug routine: check that records are in the right order.
*/
void
xfs_btree_check_rec(
xfs_btnum_t btnum, /* btree identifier */
void *ar1, /* pointer to left (lower) record */
void *ar2); /* pointer to right (higher) record */
#else
#define xfs_btree_check_block(a,b,c,d)
#define xfs_btree_check_key(a,b,c)
#define xfs_btree_check_rec(a,b,c)
#endif /* DEBUG */
/*
* Checking routine: check that long form block header is ok.
*/
int /* error (0 or EFSCORRUPTED) */
xfs_btree_check_lblock(
xfs_btree_cur_t *cur, /* btree cursor */
xfs_btree_lblock_t *block, /* btree long form block pointer */
int level, /* level of the btree block */
struct xfs_buf *bp); /* buffer containing block, if any */
/*
* Checking routine: check that (long) pointer is ok.
*/
int /* error (0 or EFSCORRUPTED) */
xfs_btree_check_lptr(
xfs_btree_cur_t *cur, /* btree cursor */
xfs_dfsbno_t ptr, /* btree block disk address */
int level); /* btree block level */
/*
* Checking routine: check that short form block header is ok.
*/
int /* error (0 or EFSCORRUPTED) */
xfs_btree_check_sblock(
xfs_btree_cur_t *cur, /* btree cursor */
xfs_btree_sblock_t *block, /* btree short form block pointer */
int level, /* level of the btree block */
struct xfs_buf *bp); /* buffer containing block */
/*
* Checking routine: check that (short) pointer is ok.
*/
int /* error (0 or EFSCORRUPTED) */
xfs_btree_check_sptr(
xfs_btree_cur_t *cur, /* btree cursor */
xfs_agblock_t ptr, /* btree block disk address */
int level); /* btree block level */
/*
* Delete the btree cursor.
*/
void
xfs_btree_del_cursor(
xfs_btree_cur_t *cur, /* btree cursor */
int error); /* del because of error */
/*
* Duplicate the btree cursor.
* Allocate a new one, copy the record, re-get the buffers.
*/
int /* error */
xfs_btree_dup_cursor(
xfs_btree_cur_t *cur, /* input cursor */
xfs_btree_cur_t **ncur);/* output cursor */
/*
* Change the cursor to point to the first record in the current block
* at the given level. Other levels are unaffected.
*/
int /* success=1, failure=0 */
xfs_btree_firstrec(
xfs_btree_cur_t *cur, /* btree cursor */
int level); /* level to change */
/*
* Get a buffer for the block, return it with no data read.
* Long-form addressing.
*/
struct xfs_buf * /* buffer for fsbno */
xfs_btree_get_bufl(
struct xfs_mount *mp, /* file system mount point */
struct xfs_trans *tp, /* transaction pointer */
xfs_fsblock_t fsbno, /* file system block number */
uint lock); /* lock flags for get_buf */
/*
* Get a buffer for the block, return it with no data read.
* Short-form addressing.
*/
struct xfs_buf * /* buffer for agno/agbno */
xfs_btree_get_bufs(
struct xfs_mount *mp, /* file system mount point */
struct xfs_trans *tp, /* transaction pointer */
xfs_agnumber_t agno, /* allocation group number */
xfs_agblock_t agbno, /* allocation group block number */
uint lock); /* lock flags for get_buf */
/*
* Allocate a new btree cursor.
* The cursor is either for allocation (A) or bmap (B).
*/
xfs_btree_cur_t * /* new btree cursor */
xfs_btree_init_cursor(
struct xfs_mount *mp, /* file system mount point */
struct xfs_trans *tp, /* transaction pointer */
struct xfs_buf *agbp, /* (A only) buffer for agf structure */
xfs_agnumber_t agno, /* (A only) allocation group number */
xfs_btnum_t btnum, /* btree identifier */
struct xfs_inode *ip, /* (B only) inode owning the btree */
int whichfork); /* (B only) data/attr fork */
/*
* Check for the cursor referring to the last block at the given level.
*/
int /* 1=is last block, 0=not last block */
xfs_btree_islastblock(
xfs_btree_cur_t *cur, /* btree cursor */
int level); /* level to check */
/*
* Change the cursor to point to the last record in the current block
* at the given level. Other levels are unaffected.
*/
int /* success=1, failure=0 */
xfs_btree_lastrec(
xfs_btree_cur_t *cur, /* btree cursor */
int level); /* level to change */
/*
* Compute first and last byte offsets for the fields given.
* Interprets the offsets table, which contains struct field offsets.
*/
void
xfs_btree_offsets(
__int64_t fields, /* bitmask of fields */
const short *offsets,/* table of field offsets */
int nbits, /* number of bits to inspect */
int *first, /* output: first byte offset */
int *last); /* output: last byte offset */
/*
* Get a buffer for the block, return it read in.
* Long-form addressing.
*/
int /* error */
xfs_btree_read_bufl(
struct xfs_mount *mp, /* file system mount point */
struct xfs_trans *tp, /* transaction pointer */
xfs_fsblock_t fsbno, /* file system block number */
uint lock, /* lock flags for read_buf */
struct xfs_buf **bpp, /* buffer for fsbno */
int refval);/* ref count value for buffer */
/*
* Get a buffer for the block, return it read in.
* Short-form addressing.
*/
int /* error */
xfs_btree_read_bufs(
struct xfs_mount *mp, /* file system mount point */
struct xfs_trans *tp, /* transaction pointer */
xfs_agnumber_t agno, /* allocation group number */
xfs_agblock_t agbno, /* allocation group block number */
uint lock, /* lock flags for read_buf */
struct xfs_buf **bpp, /* buffer for agno/agbno */
int refval);/* ref count value for buffer */
/*
* Read-ahead the block, don't wait for it, don't return a buffer.
* Long-form addressing.
*/
void /* error */
xfs_btree_reada_bufl(
struct xfs_mount *mp, /* file system mount point */
xfs_fsblock_t fsbno, /* file system block number */
xfs_extlen_t count); /* count of filesystem blocks */
/*
* Read-ahead the block, don't wait for it, don't return a buffer.
* Short-form addressing.
*/
void /* error */
xfs_btree_reada_bufs(
struct xfs_mount *mp, /* file system mount point */
xfs_agnumber_t agno, /* allocation group number */
xfs_agblock_t agbno, /* allocation group block number */
xfs_extlen_t count); /* count of filesystem blocks */
/*
* Read-ahead btree blocks, at the given level.
* Bits in lr are set from XFS_BTCUR_{LEFT,RIGHT}RA.
*/
int /* readahead block count */
xfs_btree_readahead_core(
xfs_btree_cur_t *cur, /* btree cursor */
int lev, /* level in btree */
int lr); /* left/right bits */
static inline int /* readahead block count */
xfs_btree_readahead(
xfs_btree_cur_t *cur, /* btree cursor */
int lev, /* level in btree */
int lr) /* left/right bits */
{
if ((cur->bc_ra[lev] | lr) == cur->bc_ra[lev])
return 0;
return xfs_btree_readahead_core(cur, lev, lr);
}
/*
* Set the buffer for level "lev" in the cursor to bp, releasing
* any previous buffer.
*/
void
xfs_btree_setbuf(
xfs_btree_cur_t *cur, /* btree cursor */
int lev, /* level in btree */
struct xfs_buf *bp); /* new buffer to set */
#endif /* __KERNEL__ */
/*
* Min and max functions for extlen, agblock, fileoff, and filblks types.
*/
#define XFS_EXTLEN_MIN(a,b) \
((xfs_extlen_t)(a) < (xfs_extlen_t)(b) ? \
(xfs_extlen_t)(a) : (xfs_extlen_t)(b))
#define XFS_EXTLEN_MAX(a,b) \
((xfs_extlen_t)(a) > (xfs_extlen_t)(b) ? \
(xfs_extlen_t)(a) : (xfs_extlen_t)(b))
#define XFS_AGBLOCK_MIN(a,b) \
((xfs_agblock_t)(a) < (xfs_agblock_t)(b) ? \
(xfs_agblock_t)(a) : (xfs_agblock_t)(b))
#define XFS_AGBLOCK_MAX(a,b) \
((xfs_agblock_t)(a) > (xfs_agblock_t)(b) ? \
(xfs_agblock_t)(a) : (xfs_agblock_t)(b))
#define XFS_FILEOFF_MIN(a,b) \
((xfs_fileoff_t)(a) < (xfs_fileoff_t)(b) ? \
(xfs_fileoff_t)(a) : (xfs_fileoff_t)(b))
#define XFS_FILEOFF_MAX(a,b) \
((xfs_fileoff_t)(a) > (xfs_fileoff_t)(b) ? \
(xfs_fileoff_t)(a) : (xfs_fileoff_t)(b))
#define XFS_FILBLKS_MIN(a,b) \
((xfs_filblks_t)(a) < (xfs_filblks_t)(b) ? \
(xfs_filblks_t)(a) : (xfs_filblks_t)(b))
#define XFS_FILBLKS_MAX(a,b) \
((xfs_filblks_t)(a) > (xfs_filblks_t)(b) ? \
(xfs_filblks_t)(a) : (xfs_filblks_t)(b))
#define XFS_FSB_SANITY_CHECK(mp,fsb) \
(XFS_FSB_TO_AGNO(mp, fsb) < mp->m_sb.sb_agcount && \
XFS_FSB_TO_AGBNO(mp, fsb) < mp->m_sb.sb_agblocks)
#endif /* __XFS_BTREE_H__ */

File diff suppressed because it is too large Load Diff

View File

@ -1,157 +0,0 @@
/*
* Copyright (c) 2000-2001,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
*/
#ifndef __XFS_BUF_ITEM_H__
#define __XFS_BUF_ITEM_H__
/*
* This is the structure used to lay out a buf log item in the
* log. The data map describes which 128 byte chunks of the buffer
* have been logged. This structure works only on buffers that
* reside up to the first TB in the filesystem. These buffers are
* generated only by pre-6.2 systems and are known as XFS_LI_6_1_BUF.
*/
typedef struct xfs_buf_log_format_v1 {
unsigned short blf_type; /* buf log item type indicator */
unsigned short blf_size; /* size of this item */
__int32_t blf_blkno; /* starting blkno of this buf */
ushort blf_flags; /* misc state */
ushort blf_len; /* number of blocks in this buf */
unsigned int blf_map_size; /* size of data bitmap in words */
unsigned int blf_data_map[1];/* variable size bitmap of */
/* regions of buffer in this item */
} xfs_buf_log_format_v1_t;
/*
* This is a form of the above structure with a 64 bit blkno field.
* For 6.2 and beyond, this is XFS_LI_BUF. We use this to log everything.
*/
typedef struct xfs_buf_log_format_t {
unsigned short blf_type; /* buf log item type indicator */
unsigned short blf_size; /* size of this item */
ushort blf_flags; /* misc state */
ushort blf_len; /* number of blocks in this buf */
__int64_t blf_blkno; /* starting blkno of this buf */
unsigned int blf_map_size; /* size of data bitmap in words */
unsigned int blf_data_map[1];/* variable size bitmap of */
/* regions of buffer in this item */
} xfs_buf_log_format_t;
/*
* This flag indicates that the buffer contains on disk inodes
* and requires special recovery handling.
*/
#define XFS_BLI_INODE_BUF 0x1
/*
* This flag indicates that the buffer should not be replayed
* during recovery because its blocks are being freed.
*/
#define XFS_BLI_CANCEL 0x2
/*
* This flag indicates that the buffer contains on disk
* user or group dquots and may require special recovery handling.
*/
#define XFS_BLI_UDQUOT_BUF 0x4
#define XFS_BLI_PDQUOT_BUF 0x8
#define XFS_BLI_GDQUOT_BUF 0x10
#define XFS_BLI_CHUNK 128
#define XFS_BLI_SHIFT 7
#define BIT_TO_WORD_SHIFT 5
#define NBWORD (NBBY * sizeof(unsigned int))
/*
* buf log item flags
*/
#define XFS_BLI_HOLD 0x01
#define XFS_BLI_DIRTY 0x02
#define XFS_BLI_STALE 0x04
#define XFS_BLI_LOGGED 0x08
#define XFS_BLI_INODE_ALLOC_BUF 0x10
#define XFS_BLI_STALE_INODE 0x20
#ifdef __KERNEL__
struct xfs_buf;
struct ktrace;
struct xfs_mount;
struct xfs_buf_log_item;
#if defined(XFS_BLI_TRACE)
#define XFS_BLI_TRACE_SIZE 32
void xfs_buf_item_trace(char *, struct xfs_buf_log_item *);
#else
#define xfs_buf_item_trace(id, bip)
#endif
/*
* This is the in core log item structure used to track information
* needed to log buffers. It tracks how many times the lock has been
* locked, and which 128 byte chunks of the buffer are dirty.
*/
typedef struct xfs_buf_log_item {
xfs_log_item_t bli_item; /* common item structure */
struct xfs_buf *bli_buf; /* real buffer pointer */
unsigned int bli_flags; /* misc flags */
unsigned int bli_recur; /* lock recursion count */
atomic_t bli_refcount; /* cnt of tp refs */
#ifdef XFS_BLI_TRACE
struct ktrace *bli_trace; /* event trace buf */
#endif
#ifdef XFS_TRANS_DEBUG
char *bli_orig; /* original buffer copy */
char *bli_logged; /* bytes logged (bitmap) */
#endif
xfs_buf_log_format_t bli_format; /* in-log header */
} xfs_buf_log_item_t;
/*
* This structure is used during recovery to record the buf log
* items which have been canceled and should not be replayed.
*/
typedef struct xfs_buf_cancel {
xfs_daddr_t bc_blkno;
uint bc_len;
int bc_refcount;
struct xfs_buf_cancel *bc_next;
} xfs_buf_cancel_t;
void xfs_buf_item_init(struct xfs_buf *, struct xfs_mount *);
void xfs_buf_item_relse(struct xfs_buf *);
void xfs_buf_item_log(xfs_buf_log_item_t *, uint, uint);
uint xfs_buf_item_dirty(xfs_buf_log_item_t *);
void xfs_buf_attach_iodone(struct xfs_buf *,
void(*)(struct xfs_buf *, xfs_log_item_t *),
xfs_log_item_t *);
void xfs_buf_iodone_callbacks(struct xfs_buf *);
void xfs_buf_iodone(struct xfs_buf *, xfs_buf_log_item_t *);
#ifdef XFS_TRANS_DEBUG
void
xfs_buf_item_flush_log_debug(
struct xfs_buf *bp,
uint first,
uint last);
#else
#define xfs_buf_item_flush_log_debug(bp, first, last)
#endif
#endif /* __KERNEL__ */
#endif /* __XFS_BUF_ITEM_H__ */

View File

@ -1,207 +0,0 @@
/*
* Copyright (c) 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/
*/
#include "xfs.h"
STATIC int xfs_cap_allow_set(xfs_vnode_t *);
/*
* Test for existence of capability attribute as efficiently as possible.
*/
int
xfs_cap_vhascap(
xfs_vnode_t *vp)
{
int error;
int len = sizeof(xfs_cap_set_t);
int flags = ATTR_KERNOVAL|ATTR_ROOT;
XVOP_ATTR_GET(vp, SGI_CAP_LINUX, NULL, &len, flags, sys_cred, error);
return (error == 0);
}
/*
* Convert from extended attribute representation to in-memory for XFS.
*/
STATIC int
posix_cap_xattr_to_xfs(
posix_cap_xattr *src,
size_t size,
xfs_cap_set_t *dest)
{
if (!src || !dest)
return EINVAL;
if (src->c_version != cpu_to_le32(POSIX_CAP_XATTR_VERSION))
return EINVAL;
if (src->c_abiversion != cpu_to_le32(_LINUX_CAPABILITY_VERSION))
return EINVAL;
if (size < sizeof(posix_cap_xattr))
return EINVAL;
ASSERT(sizeof(dest->cap_effective) == sizeof(src->c_effective));
dest->cap_effective = src->c_effective;
dest->cap_permitted = src->c_permitted;
dest->cap_inheritable = src->c_inheritable;
return 0;
}
/*
* Convert from in-memory XFS to extended attribute representation.
*/
STATIC int
posix_cap_xfs_to_xattr(
xfs_cap_set_t *src,
posix_cap_xattr *xattr_cap,
size_t size)
{
size_t new_size = posix_cap_xattr_size();
if (size < new_size)
return -ERANGE;
ASSERT(sizeof(xattr_cap->c_effective) == sizeof(src->cap_effective));
xattr_cap->c_version = cpu_to_le32(POSIX_CAP_XATTR_VERSION);
xattr_cap->c_abiversion = cpu_to_le32(_LINUX_CAPABILITY_VERSION);
xattr_cap->c_effective = src->cap_effective;
xattr_cap->c_permitted = src->cap_permitted;
xattr_cap->c_inheritable= src->cap_inheritable;
return new_size;
}
int
xfs_cap_vget(
xfs_vnode_t *vp,
void *cap,
size_t size)
{
int error;
int len = sizeof(xfs_cap_set_t);
int flags = ATTR_ROOT;
xfs_cap_set_t xfs_cap = { 0 };
posix_cap_xattr *xattr_cap = cap;
char *data = (char *)&xfs_cap;
VN_HOLD(vp);
if ((error = _MAC_VACCESS(vp, NULL, VREAD)))
goto out;
if (!size) {
flags |= ATTR_KERNOVAL;
data = NULL;
}
XVOP_ATTR_GET(vp, SGI_CAP_LINUX, data, &len, flags, sys_cred, error);
if (error)
goto out;
ASSERT(len == sizeof(xfs_cap_set_t));
error = (size)? -posix_cap_xattr_size() :
-posix_cap_xfs_to_xattr(&xfs_cap, xattr_cap, size);
out:
VN_RELE(vp);
return -error;
}
int
xfs_cap_vremove(
xfs_vnode_t *vp)
{
int error;
VN_HOLD(vp);
error = xfs_cap_allow_set(vp);
if (!error) {
XVOP_ATTR_REMOVE(vp, SGI_CAP_LINUX, ATTR_ROOT, sys_cred, error);
if (error == ENOATTR)
error = 0; /* 'scool */
}
VN_RELE(vp);
return -error;
}
int
xfs_cap_vset(
xfs_vnode_t *vp,
void *cap,
size_t size)
{
posix_cap_xattr *xattr_cap = cap;
xfs_cap_set_t xfs_cap;
int error;
if (!cap)
return -EINVAL;
error = posix_cap_xattr_to_xfs(xattr_cap, size, &xfs_cap);
if (error)
return -error;
VN_HOLD(vp);
error = xfs_cap_allow_set(vp);
if (error)
goto out;
XVOP_ATTR_SET(vp, SGI_CAP_LINUX, (char *)&xfs_cap,
sizeof(xfs_cap_set_t), ATTR_ROOT, sys_cred, error);
out:
VN_RELE(vp);
return -error;
}
STATIC int
xfs_cap_allow_set(
xfs_vnode_t *vp)
{
vattr_t va;
int error;
if (vp->v_vfsp->vfs_flag & VFS_RDONLY)
return EROFS;
if (vp->v_inode.i_flags & (S_IMMUTABLE|S_APPEND))
return EPERM;
if ((error = _MAC_VACCESS(vp, NULL, VWRITE)))
return error;
va.va_mask = XFS_AT_UID;
XVOP_GETATTR(vp, &va, 0, NULL, error);
if (error)
return error;
if (va.va_uid != current->fsuid && !capable(CAP_FOWNER))
return EPERM;
return error;
}

View File

@ -1,70 +0,0 @@
/*
* Copyright (c) 2000-2002,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
*/
#ifndef __XFS_CAP_H__
#define __XFS_CAP_H__
/*
* Capabilities
*/
typedef __uint64_t xfs_cap_value_t;
typedef struct xfs_cap_set {
xfs_cap_value_t cap_effective; /* use in capability checks */
xfs_cap_value_t cap_permitted; /* combined with file attrs */
xfs_cap_value_t cap_inheritable;/* pass through exec */
} xfs_cap_set_t;
/* On-disk XFS extended attribute names */
#define SGI_CAP_FILE "SGI_CAP_FILE"
#define SGI_CAP_FILE_SIZE (sizeof(SGI_CAP_FILE)-1)
#define SGI_CAP_LINUX "SGI_CAP_LINUX"
#define SGI_CAP_LINUX_SIZE (sizeof(SGI_CAP_LINUX)-1)
/*
* For Linux, we take the bitfields directly from capability.h
* and no longer attempt to keep this attribute ondisk compatible
* with IRIX. Since this attribute is only set on executables,
* it just doesn't make much sense to try. We do use a different
* named attribute though, to avoid confusion.
*/
#ifdef __KERNEL__
#ifdef CONFIG_FS_POSIX_CAP
#include <linux/posix_cap_xattr.h>
struct xfs_vnode;
extern int xfs_cap_vhascap(struct xfs_vnode *);
extern int xfs_cap_vset(struct xfs_vnode *, void *, size_t);
extern int xfs_cap_vget(struct xfs_vnode *, void *, size_t);
extern int xfs_cap_vremove(struct xfs_vnode *vp);
#define _CAP_EXISTS xfs_cap_vhascap
#else
#define xfs_cap_vset(v,p,sz) (-EOPNOTSUPP)
#define xfs_cap_vget(v,p,sz) (-EOPNOTSUPP)
#define xfs_cap_vremove(v) (-EOPNOTSUPP)
#define _CAP_EXISTS (NULL)
#endif
#endif /* __KERNEL__ */
#endif /* __XFS_CAP_H__ */

View File

@ -1,103 +0,0 @@
/*
* Copyright (c) 2000-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
*/
#ifndef __XFS_CLNT_H__
#define __XFS_CLNT_H__
/*
* XFS arguments structure, constructed from the arguments we
* are passed via the mount system call.
*
* NOTE: The mount system call is handled differently between
* Linux and IRIX. In IRIX we worked work with a binary data
* structure coming in across the syscall interface from user
* space (the mount userspace knows about each filesystem type
* and the set of valid options for it, and converts the users
* argument string into a binary structure _before_ making the
* system call), and the ABI issues that this implies.
*
* In Linux, we are passed a comma separated set of options;
* ie. a NULL terminated string of characters. Userspace mount
* code does not have any knowledge of mount options expected by
* each filesystem type and so each filesystem parses its mount
* options in kernel space.
*
* For the Linux port, we kept this structure pretty much intact
* and use it internally (because the existing code groks it).
*/
struct xfs_mount_args {
int flags; /* flags -> see XFSMNT_... macros below */
int flags2; /* flags -> see XFSMNT2_... macros below */
int logbufs; /* Number of log buffers, -1 to default */
int logbufsize; /* Size of log buffers, -1 to default */
char fsname[MAXNAMELEN+1]; /* data device name */
char rtname[MAXNAMELEN+1]; /* realtime device filename */
char logname[MAXNAMELEN+1]; /* journal device filename */
char mtpt[MAXNAMELEN+1]; /* filesystem mount point */
int sunit; /* stripe unit (BBs) */
int swidth; /* stripe width (BBs), multiple of sunit */
uchar_t iosizelog; /* log2 of the preferred I/O size */
int ihashsize; /* inode hash table size (buckets) */
};
/*
* XFS mount option flags -- args->flags1
*/
#define XFSMNT_ATTR2 0x00000001 /* allow ATTR2 EA format */
#define XFSMNT_WSYNC 0x00000002 /* safe mode nfs mount
* compatible */
#define XFSMNT_INO64 0x00000004 /* move inode numbers up
* past 2^32 */
#define XFSMNT_UQUOTA 0x00000008 /* user quota accounting */
#define XFSMNT_PQUOTA 0x00000010 /* IRIX prj quota accounting */
#define XFSMNT_UQUOTAENF 0x00000020 /* user quota limit
* enforcement */
#define XFSMNT_PQUOTAENF 0x00000040 /* IRIX project quota limit
* enforcement */
#define XFSMNT_QUIET 0x00000080 /* don't report mount errors */
#define XFSMNT_NOALIGN 0x00000200 /* don't allocate at
* stripe boundaries*/
#define XFSMNT_RETERR 0x00000400 /* return error to user */
#define XFSMNT_NORECOVERY 0x00000800 /* no recovery, implies
* read-only mount */
#define XFSMNT_SHARED 0x00001000 /* shared XFS mount */
#define XFSMNT_IOSIZE 0x00002000 /* optimize for I/O size */
#define XFSMNT_OSYNCISOSYNC 0x00004000 /* o_sync is REALLY o_sync */
/* (osyncisdsync is default) */
#define XFSMNT_32BITINODES 0x00200000 /* restrict inodes to 32
* bits of address space */
#define XFSMNT_GQUOTA 0x00400000 /* group quota accounting */
#define XFSMNT_GQUOTAENF 0x00800000 /* group quota limit
* enforcement */
#define XFSMNT_NOUUID 0x01000000 /* Ignore fs uuid */
#define XFSMNT_DMAPI 0x02000000 /* enable dmapi/xdsm */
#define XFSMNT_BARRIER 0x04000000 /* use write barriers */
#define XFSMNT_IDELETE 0x08000000 /* inode cluster delete */
#define XFSMNT_SWALLOC 0x10000000 /* turn on stripe width
* allocation */
#define XFSMNT_IHASHSIZE 0x20000000 /* inode hash table size */
#define XFSMNT_DIRSYNC 0x40000000 /* sync creat,link,unlink,rename
* symlink,mkdir,rmdir,mknod */
#define XFSMNT_FLAGS2 0x80000000 /* more flags set in flags2 */
/*
* XFS mount option flags -- args->flags2
*/
#define XFSMNT2_COMPAT_IOSIZE 0x00000001 /* don't report large preferred
* I/O size in stat(2) */
#endif /* __XFS_CLNT_H__ */

File diff suppressed because it is too large Load Diff

View File

@ -1,270 +0,0 @@
/*
* Copyright (c) 2000,2002,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
*/
#ifndef __XFS_DA_BTREE_H__
#define __XFS_DA_BTREE_H__
struct xfs_buf;
struct xfs_bmap_free;
struct xfs_inode;
struct xfs_mount;
struct xfs_trans;
struct zone;
/*========================================================================
* Directory Structure when greater than XFS_LBSIZE(mp) bytes.
*========================================================================*/
/*
* This structure is common to both leaf nodes and non-leaf nodes in the Btree.
*
* Is is used to manage a doubly linked list of all blocks at the same
* level in the Btree, and to identify which type of block this is.
*/
#define XFS_DA_NODE_MAGIC 0xfebe /* magic number: non-leaf blocks */
#define XFS_DIR_LEAF_MAGIC 0xfeeb /* magic number: directory leaf blks */
#define XFS_ATTR_LEAF_MAGIC 0xfbee /* magic number: attribute leaf blks */
#define XFS_DIR2_LEAF1_MAGIC 0xd2f1 /* magic number: v2 dirlf single blks */
#define XFS_DIR2_LEAFN_MAGIC 0xd2ff /* magic number: v2 dirlf multi blks */
#define XFS_DIRX_LEAF_MAGIC(mp) \
(XFS_DIR_IS_V1(mp) ? XFS_DIR_LEAF_MAGIC : XFS_DIR2_LEAFN_MAGIC)
typedef struct xfs_da_blkinfo {
__be32 forw; /* previous block in list */
__be32 back; /* following block in list */
__be16 magic; /* validity check on block */
__be16 pad; /* unused */
} xfs_da_blkinfo_t;
/*
* This is the structure of the root and intermediate nodes in the Btree.
* The leaf nodes are defined above.
*
* Entries are not packed.
*
* Since we have duplicate keys, use a binary search but always follow
* all match in the block, not just the first match found.
*/
#define XFS_DA_NODE_MAXDEPTH 5 /* max depth of Btree */
typedef struct xfs_da_intnode {
struct xfs_da_node_hdr { /* constant-structure header block */
xfs_da_blkinfo_t info; /* block type, links, etc. */
__be16 count; /* count of active entries */
__be16 level; /* level above leaves (leaf == 0) */
} hdr;
struct xfs_da_node_entry {
__be32 hashval; /* hash value for this descendant */
__be32 before; /* Btree block before this key */
} btree[1]; /* variable sized array of keys */
} xfs_da_intnode_t;
typedef struct xfs_da_node_hdr xfs_da_node_hdr_t;
typedef struct xfs_da_node_entry xfs_da_node_entry_t;
#define XFS_DA_MAXHASH ((xfs_dahash_t)-1) /* largest valid hash value */
#define XFS_LBSIZE(mp) (mp)->m_sb.sb_blocksize
#define XFS_LBLOG(mp) (mp)->m_sb.sb_blocklog
#define XFS_DA_MAKE_BNOENTRY(mp,bno,entry) \
(((bno) << (mp)->m_dircook_elog) | (entry))
#define XFS_DA_MAKE_COOKIE(mp,bno,entry,hash) \
(((xfs_off_t)XFS_DA_MAKE_BNOENTRY(mp, bno, entry) << 32) | (hash))
#define XFS_DA_COOKIE_HASH(mp,cookie) ((xfs_dahash_t)cookie)
#define XFS_DA_COOKIE_BNO(mp,cookie) \
((((xfs_off_t)(cookie) >> 31) == -1LL ? \
(xfs_dablk_t)0 : \
(xfs_dablk_t)((xfs_off_t)(cookie) >> \
((mp)->m_dircook_elog + 32))))
#define XFS_DA_COOKIE_ENTRY(mp,cookie) \
((((xfs_off_t)(cookie) >> 31) == -1LL ? \
(xfs_dablk_t)0 : \
(xfs_dablk_t)(((xfs_off_t)(cookie) >> 32) & \
((1 << (mp)->m_dircook_elog) - 1))))
/*========================================================================
* Btree searching and modification structure definitions.
*========================================================================*/
/*
* Structure to ease passing around component names.
*/
typedef struct xfs_da_args {
const uchar_t *name; /* string (maybe not NULL terminated) */
int namelen; /* length of string (maybe no NULL) */
uchar_t *value; /* set of bytes (maybe contain NULLs) */
int valuelen; /* length of value */
int flags; /* argument flags (eg: ATTR_NOCREATE) */
xfs_dahash_t hashval; /* hash value of name */
xfs_ino_t inumber; /* input/output inode number */
struct xfs_inode *dp; /* directory inode to manipulate */
xfs_fsblock_t *firstblock; /* ptr to firstblock for bmap calls */
struct xfs_bmap_free *flist; /* ptr to freelist for bmap_finish */
struct xfs_trans *trans; /* current trans (changes over time) */
xfs_extlen_t total; /* total blocks needed, for 1st bmap */
int whichfork; /* data or attribute fork */
xfs_dablk_t blkno; /* blkno of attr leaf of interest */
int index; /* index of attr of interest in blk */
xfs_dablk_t rmtblkno; /* remote attr value starting blkno */
int rmtblkcnt; /* remote attr value block count */
xfs_dablk_t blkno2; /* blkno of 2nd attr leaf of interest */
int index2; /* index of 2nd attr in blk */
xfs_dablk_t rmtblkno2; /* remote attr value starting blkno */
int rmtblkcnt2; /* remote attr value block count */
unsigned char justcheck; /* T/F: check for ok with no space */
unsigned char rename; /* T/F: this is an atomic rename op */
unsigned char addname; /* T/F: this is an add operation */
unsigned char oknoent; /* T/F: ok to return ENOENT, else die */
} xfs_da_args_t;
/*
* Structure to describe buffer(s) for a block.
* This is needed in the directory version 2 format case, when
* multiple non-contiguous fsblocks might be needed to cover one
* logical directory block.
* If the buffer count is 1 then the data pointer points to the
* same place as the b_addr field for the buffer, else to kmem_alloced memory.
*/
typedef struct xfs_dabuf {
int nbuf; /* number of buffer pointers present */
short dirty; /* data needs to be copied back */
short bbcount; /* how large is data in bbs */
void *data; /* pointer for buffers' data */
#ifdef XFS_DABUF_DEBUG
inst_t *ra; /* return address of caller to make */
struct xfs_dabuf *next; /* next in global chain */
struct xfs_dabuf *prev; /* previous in global chain */
struct xfs_buftarg *target; /* device for buffer */
xfs_daddr_t blkno; /* daddr first in bps[0] */
#endif
struct xfs_buf *bps[1]; /* actually nbuf of these */
} xfs_dabuf_t;
#define XFS_DA_BUF_SIZE(n) \
(sizeof(xfs_dabuf_t) + sizeof(struct xfs_buf *) * ((n) - 1))
#ifdef XFS_DABUF_DEBUG
extern xfs_dabuf_t *xfs_dabuf_global_list;
#endif
/*
* Storage for holding state during Btree searches and split/join ops.
*
* Only need space for 5 intermediate nodes. With a minimum of 62-way
* fanout to the Btree, we can support over 900 million directory blocks,
* which is slightly more than enough.
*/
typedef struct xfs_da_state_blk {
xfs_dabuf_t *bp; /* buffer containing block */
xfs_dablk_t blkno; /* filesystem blkno of buffer */
xfs_daddr_t disk_blkno; /* on-disk blkno (in BBs) of buffer */
int index; /* relevant index into block */
xfs_dahash_t hashval; /* last hash value in block */
int magic; /* blk's magic number, ie: blk type */
} xfs_da_state_blk_t;
typedef struct xfs_da_state_path {
int active; /* number of active levels */
xfs_da_state_blk_t blk[XFS_DA_NODE_MAXDEPTH];
} xfs_da_state_path_t;
typedef struct xfs_da_state {
xfs_da_args_t *args; /* filename arguments */
struct xfs_mount *mp; /* filesystem mount point */
unsigned int blocksize; /* logical block size */
unsigned int node_ents; /* how many entries in danode */
xfs_da_state_path_t path; /* search/split paths */
xfs_da_state_path_t altpath; /* alternate path for join */
unsigned char inleaf; /* insert into 1->lf, 0->splf */
unsigned char extravalid; /* T/F: extrablk is in use */
unsigned char extraafter; /* T/F: extrablk is after new */
xfs_da_state_blk_t extrablk; /* for double-splits on leafs */
/* for dirv2 extrablk is data */
} xfs_da_state_t;
/*
* Utility macros to aid in logging changed structure fields.
*/
#define XFS_DA_LOGOFF(BASE, ADDR) ((char *)(ADDR) - (char *)(BASE))
#define XFS_DA_LOGRANGE(BASE, ADDR, SIZE) \
(uint)(XFS_DA_LOGOFF(BASE, ADDR)), \
(uint)(XFS_DA_LOGOFF(BASE, ADDR)+(SIZE)-1)
#ifdef __KERNEL__
/*========================================================================
* Function prototypes for the kernel.
*========================================================================*/
/*
* Routines used for growing the Btree.
*/
int xfs_da_node_create(xfs_da_args_t *args, xfs_dablk_t blkno, int level,
xfs_dabuf_t **bpp, int whichfork);
int xfs_da_split(xfs_da_state_t *state);
/*
* Routines used for shrinking the Btree.
*/
int xfs_da_join(xfs_da_state_t *state);
void xfs_da_fixhashpath(xfs_da_state_t *state,
xfs_da_state_path_t *path_to_to_fix);
/*
* Routines used for finding things in the Btree.
*/
int xfs_da_node_lookup_int(xfs_da_state_t *state, int *result);
int xfs_da_path_shift(xfs_da_state_t *state, xfs_da_state_path_t *path,
int forward, int release, int *result);
/*
* Utility routines.
*/
int xfs_da_blk_link(xfs_da_state_t *state, xfs_da_state_blk_t *old_blk,
xfs_da_state_blk_t *new_blk);
/*
* Utility routines.
*/
int xfs_da_grow_inode(xfs_da_args_t *args, xfs_dablk_t *new_blkno);
int xfs_da_get_buf(struct xfs_trans *trans, struct xfs_inode *dp,
xfs_dablk_t bno, xfs_daddr_t mappedbno,
xfs_dabuf_t **bp, int whichfork);
int xfs_da_read_buf(struct xfs_trans *trans, struct xfs_inode *dp,
xfs_dablk_t bno, xfs_daddr_t mappedbno,
xfs_dabuf_t **bpp, int whichfork);
xfs_daddr_t xfs_da_reada_buf(struct xfs_trans *trans, struct xfs_inode *dp,
xfs_dablk_t bno, int whichfork);
int xfs_da_shrink_inode(xfs_da_args_t *args, xfs_dablk_t dead_blkno,
xfs_dabuf_t *dead_buf);
uint xfs_da_hashname(const uchar_t *name_string, int name_length);
uint xfs_da_log2_roundup(uint i);
xfs_da_state_t *xfs_da_state_alloc(void);
void xfs_da_state_free(xfs_da_state_t *state);
void xfs_da_buf_done(xfs_dabuf_t *dabuf);
void xfs_da_log_buf(struct xfs_trans *tp, xfs_dabuf_t *dabuf, uint first,
uint last);
void xfs_da_brelse(struct xfs_trans *tp, xfs_dabuf_t *dabuf);
void xfs_da_binval(struct xfs_trans *tp, xfs_dabuf_t *dabuf);
xfs_daddr_t xfs_da_blkno(xfs_dabuf_t *dabuf);
extern struct kmem_zone *xfs_da_state_zone;
#endif /* __KERNEL__ */
#endif /* __XFS_DA_BTREE_H__ */

View File

@ -1,413 +0,0 @@
/*
* Copyright (c) 2000-2006 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"
#include "xfs_fs.h"
#include "xfs_types.h"
#include "xfs_bit.h"
#include "xfs_log.h"
#include "xfs_inum.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_bmap_btree.h"
#include "xfs_alloc_btree.h"
#include "xfs_ialloc_btree.h"
#include "xfs_dir_sf.h"
#include "xfs_dir2_sf.h"
#include "xfs_attr_sf.h"
#include "xfs_dinode.h"
#include "xfs_inode.h"
#include "xfs_inode_item.h"
#include "xfs_bmap.h"
#include "xfs_btree.h"
#include "xfs_ialloc.h"
#include "xfs_itable.h"
#include "xfs_dfrag.h"
#include "xfs_error.h"
#include "xfs_mac.h"
#include "xfs_rw.h"
#include <sys/capability.h>
#include <sys/file.h>
/*
* Syssgi interface for swapext
*/
int
xfs_swapext(
xfs_swapext_t __user *sxu)
{
xfs_swapext_t *sxp;
xfs_inode_t *ip=NULL, *tip=NULL;
xfs_mount_t *mp;
xfs_vnode_t *vp = NULL, *tvp = NULL;
struct vnode *bvp, *btvp;
int error = 0;
sxp = kmem_alloc(sizeof(xfs_swapext_t), KM_MAYFAIL);
if (!sxp) {
error = XFS_ERROR(ENOMEM);
goto error0;
}
struct thread *td;
struct cred *cred;
td = curthread;
cred = td->td_ucred;
if (copy_from_user(sxp, sxu, sizeof(xfs_swapext_t))) {
error = XFS_ERROR(EFAULT);
goto error0;
}
/* Pull information for the target fd */
if (fgetvp(td, (int)sxp->sx_fdtarget, CAP_READ | CAP_WRITE, &bvp)
!= 0) {
error = XFS_ERROR(EINVAL);
goto error0;
}
vp = VPTOXFSVP(bvp);
ip = xfs_vtoi(vp);
if (ip == NULL) {
error = XFS_ERROR(EBADF);
goto error0;
}
if (fgetvp(td, (int)sxp->sx_fdtmp, CAP_READ | CAP_WRITE, &btvp) != 0) {
error = XFS_ERROR(EINVAL);
goto error0;
}
tvp = VPTOXFSVP(btvp);
tip = xfs_vtoi(tvp);
if (tip == NULL) {
error = XFS_ERROR(EBADF);
goto error0;
}
if (ip->i_mount != tip->i_mount) {
error = XFS_ERROR(EINVAL);
goto error0;
}
if (ip->i_ino == tip->i_ino) {
error = XFS_ERROR(EINVAL);
goto error0;
}
mp = ip->i_mount;
if (XFS_FORCED_SHUTDOWN(mp)) {
error = XFS_ERROR(EIO);
goto error0;
}
error = XFS_SWAP_EXTENTS(mp, &ip->i_iocore, &tip->i_iocore, sxp);
error0:
#ifdef RMC
if (fp != NULL)
fput(fp);
if (tfp != NULL)
fput(tfp);
#endif
if (sxp != NULL)
kmem_free(sxp, sizeof(xfs_swapext_t));
return error;
}
int
xfs_swap_extents(
xfs_inode_t *ip,
xfs_inode_t *tip,
xfs_swapext_t *sxp)
{
xfs_mount_t *mp;
xfs_inode_t *ips[2];
xfs_trans_t *tp;
xfs_bstat_t *sbp = &sxp->sx_stat;
xfs_vnode_t *vp, *tvp;
xfs_ifork_t *tempifp, *ifp, *tifp;
int ilf_fields, tilf_fields;
static uint lock_flags = XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL;
int error = 0;
int aforkblks = 0;
int taforkblks = 0;
__uint64_t tmp;
char locked = 0;
mp = ip->i_mount;
tempifp = kmem_alloc(sizeof(xfs_ifork_t), KM_MAYFAIL);
if (!tempifp) {
error = XFS_ERROR(ENOMEM);
goto error0;
}
sbp = &sxp->sx_stat;
vp = XFS_ITOV(ip);
tvp = XFS_ITOV(tip);
/* Lock in i_ino order */
if (ip->i_ino < tip->i_ino) {
ips[0] = ip;
ips[1] = tip;
} else {
ips[0] = tip;
ips[1] = ip;
}
xfs_lock_inodes(ips, 2, 0, lock_flags);
locked = 1;
/* Check permissions */
error = xfs_iaccess(ip, VWRITE, NULL);
if (error)
goto error0;
error = xfs_iaccess(tip, VWRITE, NULL);
if (error)
goto error0;
/* Verify that both files have the same format */
if ((ip->i_d.di_mode & S_IFMT) != (tip->i_d.di_mode & S_IFMT)) {
error = XFS_ERROR(EINVAL);
goto error0;
}
/* Verify both files are either real-time or non-realtime */
if ((ip->i_d.di_flags & XFS_DIFLAG_REALTIME) !=
(tip->i_d.di_flags & XFS_DIFLAG_REALTIME)) {
error = XFS_ERROR(EINVAL);
goto error0;
}
/* Should never get a local format */
if (ip->i_d.di_format == XFS_DINODE_FMT_LOCAL ||
tip->i_d.di_format == XFS_DINODE_FMT_LOCAL) {
error = XFS_ERROR(EINVAL);
goto error0;
}
if (VN_CACHED(tvp) != 0) {
xfs_inval_cached_trace(&tip->i_iocore, 0, -1, 0, -1);
XVOP_FLUSHINVAL_PAGES(tvp, 0, -1, FI_REMAPF_LOCKED);
}
/* Verify O_DIRECT for ftmp */
if (VN_CACHED(tvp) != 0) {
error = XFS_ERROR(EINVAL);
goto error0;
}
/* Verify all data are being swapped */
if (sxp->sx_offset != 0 ||
sxp->sx_length != ip->i_d.di_size ||
sxp->sx_length != tip->i_d.di_size) {
error = XFS_ERROR(EFAULT);
goto error0;
}
/*
* If the target has extended attributes, the tmp file
* must also in order to ensure the correct data fork
* format.
*/
if ( XFS_IFORK_Q(ip) != XFS_IFORK_Q(tip) ) {
error = XFS_ERROR(EINVAL);
goto error0;
}
/*
* Compare the current change & modify times with that
* passed in. If they differ, we abort this swap.
* This is the mechanism used to ensure the calling
* process that the file was not changed out from
* under it.
*/
if ((sbp->bs_ctime.tv_sec != ip->i_d.di_ctime.t_sec) ||
(sbp->bs_ctime.tv_nsec != ip->i_d.di_ctime.t_nsec) ||
(sbp->bs_mtime.tv_sec != ip->i_d.di_mtime.t_sec) ||
(sbp->bs_mtime.tv_nsec != ip->i_d.di_mtime.t_nsec)) {
error = XFS_ERROR(EBUSY);
goto error0;
}
/* We need to fail if the file is memory mapped. Once we have tossed
* all existing pages, the page fault will have no option
* but to go to the filesystem for pages. By making the page fault call
* VOP_READ (or write in the case of autogrow) they block on the iolock
* until we have switched the extents.
*/
if (VN_MAPPED(vp)) {
error = XFS_ERROR(EBUSY);
goto error0;
}
xfs_iunlock(ip, XFS_ILOCK_EXCL);
xfs_iunlock(tip, XFS_ILOCK_EXCL);
/*
* There is a race condition here since we gave up the
* ilock. However, the data fork will not change since
* we have the iolock (locked for truncation too) so we
* are safe. We don't really care if non-io related
* fields change.
*/
XVOP_TOSS_PAGES(vp, 0, -1, FI_REMAPF);
tp = xfs_trans_alloc(mp, XFS_TRANS_SWAPEXT);
if ((error = xfs_trans_reserve(tp, 0,
XFS_ICHANGE_LOG_RES(mp), 0,
0, 0))) {
xfs_iunlock(ip, XFS_IOLOCK_EXCL);
xfs_iunlock(tip, XFS_IOLOCK_EXCL);
xfs_trans_cancel(tp, 0);
locked = 0;
goto error0;
}
xfs_lock_inodes(ips, 2, 0, XFS_ILOCK_EXCL);
/*
* Count the number of extended attribute blocks
*/
if ( ((XFS_IFORK_Q(ip) != 0) && (ip->i_d.di_anextents > 0)) &&
(ip->i_d.di_aformat != XFS_DINODE_FMT_LOCAL)) {
error = xfs_bmap_count_blocks(tp, ip, XFS_ATTR_FORK, &aforkblks);
if (error) {
xfs_trans_cancel(tp, 0);
goto error0;
}
}
if ( ((XFS_IFORK_Q(tip) != 0) && (tip->i_d.di_anextents > 0)) &&
(tip->i_d.di_aformat != XFS_DINODE_FMT_LOCAL)) {
error = xfs_bmap_count_blocks(tp, tip, XFS_ATTR_FORK,
&taforkblks);
if (error) {
xfs_trans_cancel(tp, 0);
goto error0;
}
}
/*
* Swap the data forks of the inodes
*/
ifp = &ip->i_df;
tifp = &tip->i_df;
*tempifp = *ifp; /* struct copy */
*ifp = *tifp; /* struct copy */
*tifp = *tempifp; /* struct copy */
/*
* Fix the on-disk inode values
*/
tmp = (__uint64_t)ip->i_d.di_nblocks;
ip->i_d.di_nblocks = tip->i_d.di_nblocks - taforkblks + aforkblks;
tip->i_d.di_nblocks = tmp + taforkblks - aforkblks;
tmp = (__uint64_t) ip->i_d.di_nextents;
ip->i_d.di_nextents = tip->i_d.di_nextents;
tip->i_d.di_nextents = tmp;
tmp = (__uint64_t) ip->i_d.di_format;
ip->i_d.di_format = tip->i_d.di_format;
tip->i_d.di_format = tmp;
ilf_fields = XFS_ILOG_CORE;
switch(ip->i_d.di_format) {
case XFS_DINODE_FMT_EXTENTS:
/* If the extents fit in the inode, fix the
* pointer. Otherwise it's already NULL or
* pointing to the extent.
*/
if (ip->i_d.di_nextents <= XFS_INLINE_EXTS) {
ifp->if_u1.if_extents =
ifp->if_u2.if_inline_ext;
}
ilf_fields |= XFS_ILOG_DEXT;
break;
case XFS_DINODE_FMT_BTREE:
ilf_fields |= XFS_ILOG_DBROOT;
break;
}
tilf_fields = XFS_ILOG_CORE;
switch(tip->i_d.di_format) {
case XFS_DINODE_FMT_EXTENTS:
/* If the extents fit in the inode, fix the
* pointer. Otherwise it's already NULL or
* pointing to the extent.
*/
if (tip->i_d.di_nextents <= XFS_INLINE_EXTS) {
tifp->if_u1.if_extents =
tifp->if_u2.if_inline_ext;
}
tilf_fields |= XFS_ILOG_DEXT;
break;
case XFS_DINODE_FMT_BTREE:
tilf_fields |= XFS_ILOG_DBROOT;
break;
}
#ifdef XXXKAN /* Not necessary, vnodes are vrefed already by fgetvp */
/*
* Increment vnode ref counts since xfs_trans_commit &
* xfs_trans_cancel will both unlock the inodes and
* decrement the associated ref counts.
*/
VN_HOLD(vp);
VN_HOLD(tvp);
#endif
xfs_trans_ijoin(tp, ip, lock_flags);
xfs_trans_ijoin(tp, tip, lock_flags);
xfs_trans_log_inode(tp, ip, ilf_fields);
xfs_trans_log_inode(tp, tip, tilf_fields);
/*
* If this is a synchronous mount, make sure that the
* transaction goes to disk before returning to the user.
*/
if (mp->m_flags & XFS_MOUNT_WSYNC) {
xfs_trans_set_sync(tp);
}
error = xfs_trans_commit(tp, XFS_TRANS_SWAPEXT, NULL);
locked = 0;
error0:
if (locked) {
xfs_iunlock(ip, lock_flags);
xfs_iunlock(tip, lock_flags);
}
if (tempifp != NULL)
kmem_free(tempifp, sizeof(xfs_ifork_t));
return error;
}

View File

@ -1,56 +0,0 @@
/*
* Copyright (c) 2000,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
*/
#ifndef __XFS_DFRAG_H__
#define __XFS_DFRAG_H__
/*
* Structure passed to xfs_swapext
*/
typedef struct xfs_swapext
{
__int64_t sx_version; /* version */
__int64_t sx_fdtarget; /* fd of target file */
__int64_t sx_fdtmp; /* fd of tmp file */
xfs_off_t sx_offset; /* offset into file */
xfs_off_t sx_length; /* leng from offset */
char sx_pad[16]; /* pad space, unused */
xfs_bstat_t sx_stat; /* stat of target b4 copy */
} xfs_swapext_t;
/*
* Version flag
*/
#define XFS_SX_VERSION 0
#ifdef __KERNEL__
/*
* Prototypes for visible xfs_dfrag.c routines.
*/
/*
* Syscall interface for xfs_swapext
*/
int xfs_swapext(struct xfs_swapext __user *sx);
int xfs_swap_extents(struct xfs_inode *ip, struct xfs_inode *tip,
struct xfs_swapext *sxp);
#endif /* __KERNEL__ */
#endif /* __XFS_DFRAG_H__ */

View File

@ -1,281 +0,0 @@
/*
* Copyright (c) 2000,2002,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
*/
#ifndef __XFS_DINODE_H__
#define __XFS_DINODE_H__
struct xfs_buf;
struct xfs_mount;
#define XFS_DINODE_VERSION_1 1
#define XFS_DINODE_VERSION_2 2
#define XFS_DINODE_GOOD_VERSION(v) \
(((v) == XFS_DINODE_VERSION_1 || (v) == XFS_DINODE_VERSION_2))
#define XFS_DINODE_MAGIC 0x494e /* 'IN' */
/*
* Disk inode structure.
* This is just the header; the inode is expanded to fill a variable size
* with the last field expanding. It is split into the core and "other"
* because we only need the core part in the in-core inode.
*/
typedef struct xfs_timestamp {
__int32_t t_sec; /* timestamp seconds */
__int32_t t_nsec; /* timestamp nanoseconds */
} xfs_timestamp_t;
/*
* Note: Coordinate changes to this structure with the XFS_DI_* #defines
* below and the offsets table in xfs_ialloc_log_di().
*/
typedef struct xfs_dinode_core
{
__uint16_t di_magic; /* inode magic # = XFS_DINODE_MAGIC */
__uint16_t di_mode; /* mode and type of file */
__int8_t di_version; /* inode version */
__int8_t di_format; /* format of di_c data */
__uint16_t di_onlink; /* old number of links to file */
__uint32_t di_uid; /* owner's user id */
__uint32_t di_gid; /* owner's group id */
__uint32_t di_nlink; /* number of links to file */
__uint16_t di_projid; /* owner's project id */
__uint8_t di_pad[8]; /* unused, zeroed space */
__uint16_t di_flushiter; /* incremented on flush */
xfs_timestamp_t di_atime; /* time last accessed */
xfs_timestamp_t di_mtime; /* time last modified */
xfs_timestamp_t di_ctime; /* time created/inode modified */
xfs_fsize_t di_size; /* number of bytes in file */
xfs_drfsbno_t di_nblocks; /* # of direct & btree blocks used */
xfs_extlen_t di_extsize; /* basic/minimum extent size for file */
xfs_extnum_t di_nextents; /* number of extents in data fork */
xfs_aextnum_t di_anextents; /* number of extents in attribute fork*/
__uint8_t di_forkoff; /* attr fork offs, <<3 for 64b align */
__int8_t di_aformat; /* format of attr fork's data */
__uint32_t di_dmevmask; /* DMIG event mask */
__uint16_t di_dmstate; /* DMIG state info */
__uint16_t di_flags; /* random flags, XFS_DIFLAG_... */
__uint32_t di_gen; /* generation number */
} xfs_dinode_core_t;
#define DI_MAX_FLUSH 0xffff
typedef struct xfs_dinode
{
xfs_dinode_core_t di_core;
/*
* In adding anything between the core and the union, be
* sure to update the macros like XFS_LITINO below and
* XFS_BMAP_RBLOCK_DSIZE in xfs_bmap_btree.h.
*/
xfs_agino_t di_next_unlinked;/* agi unlinked list ptr */
union {
xfs_bmdr_block_t di_bmbt; /* btree root block */
xfs_bmbt_rec_32_t di_bmx[1]; /* extent list */
xfs_dir_shortform_t di_dirsf; /* shortform directory */
xfs_dir2_sf_t di_dir2sf; /* shortform directory v2 */
char di_c[1]; /* local contents */
xfs_dev_t di_dev; /* device for S_IFCHR/S_IFBLK */
uuid_t di_muuid; /* mount point value */
char di_symlink[1]; /* local symbolic link */
} di_u;
union {
xfs_bmdr_block_t di_abmbt; /* btree root block */
xfs_bmbt_rec_32_t di_abmx[1]; /* extent list */
xfs_attr_shortform_t di_attrsf; /* shortform attribute list */
} di_a;
} xfs_dinode_t;
/*
* The 32 bit link count in the inode theoretically maxes out at UINT_MAX.
* Since the pathconf interface is signed, we use 2^31 - 1 instead.
* The old inode format had a 16 bit link count, so its maximum is USHRT_MAX.
*/
#define XFS_MAXLINK ((1U << 31) - 1U)
#define XFS_MAXLINK_1 65535U
/*
* Bit names for logging disk inodes only
*/
#define XFS_DI_MAGIC 0x0000001
#define XFS_DI_MODE 0x0000002
#define XFS_DI_VERSION 0x0000004
#define XFS_DI_FORMAT 0x0000008
#define XFS_DI_ONLINK 0x0000010
#define XFS_DI_UID 0x0000020
#define XFS_DI_GID 0x0000040
#define XFS_DI_NLINK 0x0000080
#define XFS_DI_PROJID 0x0000100
#define XFS_DI_PAD 0x0000200
#define XFS_DI_ATIME 0x0000400
#define XFS_DI_MTIME 0x0000800
#define XFS_DI_CTIME 0x0001000
#define XFS_DI_SIZE 0x0002000
#define XFS_DI_NBLOCKS 0x0004000
#define XFS_DI_EXTSIZE 0x0008000
#define XFS_DI_NEXTENTS 0x0010000
#define XFS_DI_NAEXTENTS 0x0020000
#define XFS_DI_FORKOFF 0x0040000
#define XFS_DI_AFORMAT 0x0080000
#define XFS_DI_DMEVMASK 0x0100000
#define XFS_DI_DMSTATE 0x0200000
#define XFS_DI_FLAGS 0x0400000
#define XFS_DI_GEN 0x0800000
#define XFS_DI_NEXT_UNLINKED 0x1000000
#define XFS_DI_U 0x2000000
#define XFS_DI_A 0x4000000
#define XFS_DI_NUM_BITS 27
#define XFS_DI_ALL_BITS ((1 << XFS_DI_NUM_BITS) - 1)
#define XFS_DI_CORE_BITS (XFS_DI_ALL_BITS & ~(XFS_DI_U|XFS_DI_A))
/*
* Values for di_format
*/
typedef enum xfs_dinode_fmt
{
XFS_DINODE_FMT_DEV, /* CHR, BLK: di_dev */
XFS_DINODE_FMT_LOCAL, /* DIR, REG: di_c */
/* LNK: di_symlink */
XFS_DINODE_FMT_EXTENTS, /* DIR, REG, LNK: di_bmx */
XFS_DINODE_FMT_BTREE, /* DIR, REG, LNK: di_bmbt */
XFS_DINODE_FMT_UUID /* MNT: di_uuid */
} xfs_dinode_fmt_t;
/*
* Inode minimum and maximum sizes.
*/
#define XFS_DINODE_MIN_LOG 8
#define XFS_DINODE_MAX_LOG 11
#define XFS_DINODE_MIN_SIZE (1 << XFS_DINODE_MIN_LOG)
#define XFS_DINODE_MAX_SIZE (1 << XFS_DINODE_MAX_LOG)
/*
* Inode size for given fs.
*/
#define XFS_LITINO(mp) ((mp)->m_litino)
#define XFS_BROOT_SIZE_ADJ \
(sizeof(xfs_bmbt_block_t) - sizeof(xfs_bmdr_block_t))
/*
* Inode data & attribute fork sizes, per inode.
*/
#define XFS_CFORK_Q(dcp) ((dcp)->di_forkoff != 0)
#define XFS_CFORK_Q_DISK(dcp) ((dcp)->di_forkoff != 0)
#define XFS_CFORK_BOFF(dcp) ((int)((dcp)->di_forkoff << 3))
#define XFS_CFORK_BOFF_DISK(dcp) \
((int)(INT_GET((dcp)->di_forkoff, ARCH_CONVERT) << 3))
#define XFS_CFORK_DSIZE_DISK(dcp,mp) \
(XFS_CFORK_Q_DISK(dcp) ? XFS_CFORK_BOFF_DISK(dcp) : XFS_LITINO(mp))
#define XFS_CFORK_DSIZE(dcp,mp) \
(XFS_CFORK_Q(dcp) ? XFS_CFORK_BOFF(dcp) : XFS_LITINO(mp))
#define XFS_CFORK_ASIZE_DISK(dcp,mp) \
(XFS_CFORK_Q_DISK(dcp) ? XFS_LITINO(mp) - XFS_CFORK_BOFF_DISK(dcp) : 0)
#define XFS_CFORK_ASIZE(dcp,mp) \
(XFS_CFORK_Q(dcp) ? XFS_LITINO(mp) - XFS_CFORK_BOFF(dcp) : 0)
#define XFS_CFORK_SIZE_DISK(dcp,mp,w) \
((w) == XFS_DATA_FORK ? \
XFS_CFORK_DSIZE_DISK(dcp, mp) : \
XFS_CFORK_ASIZE_DISK(dcp, mp))
#define XFS_CFORK_SIZE(dcp,mp,w) \
((w) == XFS_DATA_FORK ? \
XFS_CFORK_DSIZE(dcp, mp) : XFS_CFORK_ASIZE(dcp, mp))
#define XFS_DFORK_DSIZE(dip,mp) \
XFS_CFORK_DSIZE_DISK(&(dip)->di_core, mp)
#define XFS_DFORK_DSIZE_HOST(dip,mp) \
XFS_CFORK_DSIZE(&(dip)->di_core, mp)
#define XFS_DFORK_ASIZE(dip,mp) \
XFS_CFORK_ASIZE_DISK(&(dip)->di_core, mp)
#define XFS_DFORK_ASIZE_HOST(dip,mp) \
XFS_CFORK_ASIZE(&(dip)->di_core, mp)
#define XFS_DFORK_SIZE(dip,mp,w) \
XFS_CFORK_SIZE_DISK(&(dip)->di_core, mp, w)
#define XFS_DFORK_SIZE_HOST(dip,mp,w) \
XFS_CFORK_SIZE(&(dip)->di_core, mp, w)
#define XFS_DFORK_Q(dip) XFS_CFORK_Q_DISK(&(dip)->di_core)
#define XFS_DFORK_BOFF(dip) XFS_CFORK_BOFF_DISK(&(dip)->di_core)
#define XFS_DFORK_DPTR(dip) ((dip)->di_u.di_c)
#define XFS_DFORK_APTR(dip) \
((dip)->di_u.di_c + XFS_DFORK_BOFF(dip))
#define XFS_DFORK_PTR(dip,w) \
((w) == XFS_DATA_FORK ? XFS_DFORK_DPTR(dip) : XFS_DFORK_APTR(dip))
#define XFS_CFORK_FORMAT(dcp,w) \
((w) == XFS_DATA_FORK ? (dcp)->di_format : (dcp)->di_aformat)
#define XFS_CFORK_FMT_SET(dcp,w,n) \
((w) == XFS_DATA_FORK ? \
((dcp)->di_format = (n)) : ((dcp)->di_aformat = (n)))
#define XFS_DFORK_FORMAT(dip,w) XFS_CFORK_FORMAT(&(dip)->di_core, w)
#define XFS_CFORK_NEXTENTS_DISK(dcp,w) \
((w) == XFS_DATA_FORK ? \
INT_GET((dcp)->di_nextents, ARCH_CONVERT) : \
INT_GET((dcp)->di_anextents, ARCH_CONVERT))
#define XFS_CFORK_NEXTENTS(dcp,w) \
((w) == XFS_DATA_FORK ? (dcp)->di_nextents : (dcp)->di_anextents)
#define XFS_DFORK_NEXTENTS(dip,w) XFS_CFORK_NEXTENTS_DISK(&(dip)->di_core, w)
#define XFS_DFORK_NEXTENTS_HOST(dip,w) XFS_CFORK_NEXTENTS(&(dip)->di_core, w)
#define XFS_CFORK_NEXT_SET(dcp,w,n) \
((w) == XFS_DATA_FORK ? \
((dcp)->di_nextents = (n)) : ((dcp)->di_anextents = (n)))
#define XFS_BUF_TO_DINODE(bp) ((xfs_dinode_t *)XFS_BUF_PTR(bp))
/*
* Values for di_flags
* There should be a one-to-one correspondence between these flags and the
* XFS_XFLAG_s.
*/
#define XFS_DIFLAG_REALTIME_BIT 0 /* file's blocks come from rt area */
#define XFS_DIFLAG_PREALLOC_BIT 1 /* file space has been preallocated */
#define XFS_DIFLAG_NEWRTBM_BIT 2 /* for rtbitmap inode, new format */
#define XFS_DIFLAG_IMMUTABLE_BIT 3 /* inode is immutable */
#define XFS_DIFLAG_APPEND_BIT 4 /* inode is append-only */
#define XFS_DIFLAG_SYNC_BIT 5 /* inode is written synchronously */
#define XFS_DIFLAG_NOATIME_BIT 6 /* do not update atime */
#define XFS_DIFLAG_NODUMP_BIT 7 /* do not dump */
#define XFS_DIFLAG_RTINHERIT_BIT 8 /* create with realtime bit set */
#define XFS_DIFLAG_PROJINHERIT_BIT 9 /* create with parents projid */
#define XFS_DIFLAG_NOSYMLINKS_BIT 10 /* disallow symlink creation */
#define XFS_DIFLAG_EXTSIZE_BIT 11 /* inode extent size allocator hint */
#define XFS_DIFLAG_EXTSZINHERIT_BIT 12 /* inherit inode extent size */
#define XFS_DIFLAG_REALTIME (1 << XFS_DIFLAG_REALTIME_BIT)
#define XFS_DIFLAG_PREALLOC (1 << XFS_DIFLAG_PREALLOC_BIT)
#define XFS_DIFLAG_NEWRTBM (1 << XFS_DIFLAG_NEWRTBM_BIT)
#define XFS_DIFLAG_IMMUTABLE (1 << XFS_DIFLAG_IMMUTABLE_BIT)
#define XFS_DIFLAG_APPEND (1 << XFS_DIFLAG_APPEND_BIT)
#define XFS_DIFLAG_SYNC (1 << XFS_DIFLAG_SYNC_BIT)
#define XFS_DIFLAG_NOATIME (1 << XFS_DIFLAG_NOATIME_BIT)
#define XFS_DIFLAG_NODUMP (1 << XFS_DIFLAG_NODUMP_BIT)
#define XFS_DIFLAG_RTINHERIT (1 << XFS_DIFLAG_RTINHERIT_BIT)
#define XFS_DIFLAG_PROJINHERIT (1 << XFS_DIFLAG_PROJINHERIT_BIT)
#define XFS_DIFLAG_NOSYMLINKS (1 << XFS_DIFLAG_NOSYMLINKS_BIT)
#define XFS_DIFLAG_EXTSIZE (1 << XFS_DIFLAG_EXTSIZE_BIT)
#define XFS_DIFLAG_EXTSZINHERIT (1 << XFS_DIFLAG_EXTSZINHERIT_BIT)
#define XFS_DIFLAG_ANY \
(XFS_DIFLAG_REALTIME | XFS_DIFLAG_PREALLOC | XFS_DIFLAG_NEWRTBM | \
XFS_DIFLAG_IMMUTABLE | XFS_DIFLAG_APPEND | XFS_DIFLAG_SYNC | \
XFS_DIFLAG_NOATIME | XFS_DIFLAG_NODUMP | XFS_DIFLAG_RTINHERIT | \
XFS_DIFLAG_PROJINHERIT | XFS_DIFLAG_NOSYMLINKS | XFS_DIFLAG_EXTSIZE | \
XFS_DIFLAG_EXTSZINHERIT)
#endif /* __XFS_DINODE_H__ */

File diff suppressed because it is too large Load Diff

View File

@ -1,142 +0,0 @@
/*
* Copyright (c) 2000,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
*/
#ifndef __XFS_DIR_H__
#define __XFS_DIR_H__
/*
* Large directories are structured around Btrees where all the data
* elements are in the leaf nodes. Filenames are hashed into an int,
* then that int is used as the index into the Btree. Since the hashval
* of a filename may not be unique, we may have duplicate keys. The
* internal links in the Btree are logical block offsets into the file.
*
* Small directories use a different format and are packed as tightly
* as possible so as to fit into the literal area of the inode.
*/
/*========================================================================
* Function prototypes for the kernel.
*========================================================================*/
struct uio;
struct xfs_bmap_free;
struct xfs_da_args;
struct xfs_dinode;
struct xfs_inode;
struct xfs_mount;
struct xfs_trans;
/*
* Directory function types.
* Put in structures (xfs_dirops_t) for v1 and v2 directories.
*/
typedef void (*xfs_dir_mount_t)(struct xfs_mount *mp);
typedef int (*xfs_dir_isempty_t)(struct xfs_inode *dp);
typedef int (*xfs_dir_init_t)(struct xfs_trans *tp,
struct xfs_inode *dp,
struct xfs_inode *pdp);
typedef int (*xfs_dir_createname_t)(struct xfs_trans *tp,
struct xfs_inode *dp,
char *name,
int namelen,
xfs_ino_t inum,
xfs_fsblock_t *first,
struct xfs_bmap_free *flist,
xfs_extlen_t total);
typedef int (*xfs_dir_lookup_t)(struct xfs_trans *tp,
struct xfs_inode *dp,
char *name,
int namelen,
xfs_ino_t *inum);
typedef int (*xfs_dir_removename_t)(struct xfs_trans *tp,
struct xfs_inode *dp,
char *name,
int namelen,
xfs_ino_t ino,
xfs_fsblock_t *first,
struct xfs_bmap_free *flist,
xfs_extlen_t total);
typedef int (*xfs_dir_getdents_t)(struct xfs_trans *tp,
struct xfs_inode *dp,
struct uio *uio,
int *eofp);
typedef int (*xfs_dir_replace_t)(struct xfs_trans *tp,
struct xfs_inode *dp,
char *name,
int namelen,
xfs_ino_t inum,
xfs_fsblock_t *first,
struct xfs_bmap_free *flist,
xfs_extlen_t total);
typedef int (*xfs_dir_canenter_t)(struct xfs_trans *tp,
struct xfs_inode *dp,
char *name,
int namelen);
typedef int (*xfs_dir_shortform_validate_ondisk_t)(struct xfs_mount *mp,
struct xfs_dinode *dip);
typedef int (*xfs_dir_shortform_to_single_t)(struct xfs_da_args *args);
typedef struct xfs_dirops {
xfs_dir_mount_t xd_mount;
xfs_dir_isempty_t xd_isempty;
xfs_dir_init_t xd_init;
xfs_dir_createname_t xd_createname;
xfs_dir_lookup_t xd_lookup;
xfs_dir_removename_t xd_removename;
xfs_dir_getdents_t xd_getdents;
xfs_dir_replace_t xd_replace;
xfs_dir_canenter_t xd_canenter;
xfs_dir_shortform_validate_ondisk_t xd_shortform_validate_ondisk;
xfs_dir_shortform_to_single_t xd_shortform_to_single;
} xfs_dirops_t;
/*
* Overall external interface routines.
*/
void xfs_dir_startup(void); /* called exactly once */
#define XFS_DIR_MOUNT(mp) \
((mp)->m_dirops.xd_mount(mp))
#define XFS_DIR_ISEMPTY(mp,dp) \
((mp)->m_dirops.xd_isempty(dp))
#define XFS_DIR_INIT(mp,tp,dp,pdp) \
((mp)->m_dirops.xd_init(tp,dp,pdp))
#define XFS_DIR_CREATENAME(mp,tp,dp,name,namelen,inum,first,flist,total) \
((mp)->m_dirops.xd_createname(tp,dp,name,namelen,inum,first,flist,\
total))
#define XFS_DIR_LOOKUP(mp,tp,dp,name,namelen,inum) \
((mp)->m_dirops.xd_lookup(tp,dp,name,namelen,inum))
#define XFS_DIR_REMOVENAME(mp,tp,dp,name,namelen,ino,first,flist,total) \
((mp)->m_dirops.xd_removename(tp,dp,name,namelen,ino,first,flist,total))
#define XFS_DIR_GETDENTS(mp,tp,dp,uio,eofp) \
((mp)->m_dirops.xd_getdents(tp,dp,uio,eofp))
#define XFS_DIR_REPLACE(mp,tp,dp,name,namelen,inum,first,flist,total) \
((mp)->m_dirops.xd_replace(tp,dp,name,namelen,inum,first,flist,total))
#define XFS_DIR_CANENTER(mp,tp,dp,name,namelen) \
((mp)->m_dirops.xd_canenter(tp,dp,name,namelen))
#define XFS_DIR_SHORTFORM_VALIDATE_ONDISK(mp,dip) \
((mp)->m_dirops.xd_shortform_validate_ondisk(mp,dip))
#define XFS_DIR_SHORTFORM_TO_SINGLE(mp,args) \
((mp)->m_dirops.xd_shortform_to_single(args))
#define XFS_DIR_IS_V1(mp) ((mp)->m_dirversion == 1)
#define XFS_DIR_IS_V2(mp) ((mp)->m_dirversion == 2)
extern xfs_dirops_t xfsv1_dirops;
extern xfs_dirops_t xfsv2_dirops;
#endif /* __XFS_DIR_H__ */

View File

@ -1,851 +0,0 @@
/*
* Copyright (c) 2000-2001,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"
#include "xfs_fs.h"
#include "xfs_types.h"
#include "xfs_bit.h"
#include "xfs_log.h"
#include "xfs_inum.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_da_btree.h"
#include "xfs_bmap_btree.h"
#include "xfs_alloc_btree.h"
#include "xfs_dir_sf.h"
#include "xfs_dir2_sf.h"
#include "xfs_attr_sf.h"
#include "xfs_dinode.h"
#include "xfs_inode.h"
#include "xfs_inode_item.h"
#include "xfs_bmap.h"
#include "xfs_dir_leaf.h"
#include "xfs_dir2_data.h"
#include "xfs_dir2_leaf.h"
#include "xfs_dir2_block.h"
#include "xfs_dir2_node.h"
#include "xfs_dir2_trace.h"
#include "xfs_error.h"
/*
* Declarations for interface routines.
*/
static void xfs_dir2_mount(xfs_mount_t *mp);
static int xfs_dir2_isempty(xfs_inode_t *dp);
static int xfs_dir2_init(xfs_trans_t *tp, xfs_inode_t *dp,
xfs_inode_t *pdp);
static int xfs_dir2_createname(xfs_trans_t *tp, xfs_inode_t *dp,
char *name, int namelen, xfs_ino_t inum,
xfs_fsblock_t *first,
xfs_bmap_free_t *flist, xfs_extlen_t total);
static int xfs_dir2_lookup(xfs_trans_t *tp, xfs_inode_t *dp, char *name,
int namelen, xfs_ino_t *inum);
static int xfs_dir2_removename(xfs_trans_t *tp, xfs_inode_t *dp,
char *name, int namelen, xfs_ino_t ino,
xfs_fsblock_t *first,
xfs_bmap_free_t *flist, xfs_extlen_t total);
static int xfs_dir2_getdents(xfs_trans_t *tp, xfs_inode_t *dp, uio_t *uio,
int *eofp);
static int xfs_dir2_replace(xfs_trans_t *tp, xfs_inode_t *dp, char *name,
int namelen, xfs_ino_t inum,
xfs_fsblock_t *first, xfs_bmap_free_t *flist,
xfs_extlen_t total);
static int xfs_dir2_canenter(xfs_trans_t *tp, xfs_inode_t *dp, char *name,
int namelen);
static int xfs_dir2_shortform_validate_ondisk(xfs_mount_t *mp,
xfs_dinode_t *dip);
/*
* Utility routine declarations.
*/
static int xfs_dir2_put_dirent64_direct(xfs_dir2_put_args_t *pa);
static int xfs_dir2_put_dirent64_uio(xfs_dir2_put_args_t *pa);
/*
* Directory operations vector.
*/
xfs_dirops_t xfsv2_dirops = {
.xd_mount = xfs_dir2_mount,
.xd_isempty = xfs_dir2_isempty,
.xd_init = xfs_dir2_init,
.xd_createname = xfs_dir2_createname,
.xd_lookup = xfs_dir2_lookup,
.xd_removename = xfs_dir2_removename,
.xd_getdents = xfs_dir2_getdents,
.xd_replace = xfs_dir2_replace,
.xd_canenter = xfs_dir2_canenter,
.xd_shortform_validate_ondisk = xfs_dir2_shortform_validate_ondisk,
.xd_shortform_to_single = xfs_dir2_sf_to_block,
};
/*
* Interface routines.
*/
/*
* Initialize directory-related fields in the mount structure.
*/
static void
xfs_dir2_mount(
xfs_mount_t *mp) /* filesystem mount point */
{
mp->m_dirversion = 2;
ASSERT((1 << (mp->m_sb.sb_blocklog + mp->m_sb.sb_dirblklog)) <=
XFS_MAX_BLOCKSIZE);
mp->m_dirblksize = 1 << (mp->m_sb.sb_blocklog + mp->m_sb.sb_dirblklog);
mp->m_dirblkfsbs = 1 << mp->m_sb.sb_dirblklog;
mp->m_dirdatablk = XFS_DIR2_DB_TO_DA(mp, XFS_DIR2_DATA_FIRSTDB(mp));
mp->m_dirleafblk = XFS_DIR2_DB_TO_DA(mp, XFS_DIR2_LEAF_FIRSTDB(mp));
mp->m_dirfreeblk = XFS_DIR2_DB_TO_DA(mp, XFS_DIR2_FREE_FIRSTDB(mp));
mp->m_attr_node_ents =
(mp->m_sb.sb_blocksize - (uint)sizeof(xfs_da_node_hdr_t)) /
(uint)sizeof(xfs_da_node_entry_t);
mp->m_dir_node_ents =
(mp->m_dirblksize - (uint)sizeof(xfs_da_node_hdr_t)) /
(uint)sizeof(xfs_da_node_entry_t);
mp->m_dir_magicpct = (mp->m_dirblksize * 37) / 100;
}
/*
* Return 1 if directory contains only "." and "..".
*/
static int /* return code */
xfs_dir2_isempty(
xfs_inode_t *dp) /* incore inode structure */
{
xfs_dir2_sf_t *sfp; /* shortform directory structure */
ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR);
/*
* Might happen during shutdown.
*/
if (dp->i_d.di_size == 0) {
return 1;
}
if (dp->i_d.di_size > XFS_IFORK_DSIZE(dp))
return 0;
sfp = (xfs_dir2_sf_t *)dp->i_df.if_u1.if_data;
return !sfp->hdr.count;
}
/*
* Initialize a directory with its "." and ".." entries.
*/
static int /* error */
xfs_dir2_init(
xfs_trans_t *tp, /* transaction pointer */
xfs_inode_t *dp, /* incore directory inode */
xfs_inode_t *pdp) /* incore parent directory inode */
{
xfs_da_args_t args; /* operation arguments */
int error; /* error return value */
memset((char *)&args, 0, sizeof(args));
args.dp = dp;
args.trans = tp;
ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR);
if ((error = xfs_dir_ino_validate(tp->t_mountp, pdp->i_ino))) {
return error;
}
return xfs_dir2_sf_create(&args, pdp->i_ino);
}
/*
Enter a name in a directory.
*/
static int /* error */
xfs_dir2_createname(
xfs_trans_t *tp, /* transaction pointer */
xfs_inode_t *dp, /* incore directory inode */
char *name, /* new entry name */
int namelen, /* new entry name length */
xfs_ino_t inum, /* new entry inode number */
xfs_fsblock_t *first, /* bmap's firstblock */
xfs_bmap_free_t *flist, /* bmap's freeblock list */
xfs_extlen_t total) /* bmap's total block count */
{
xfs_da_args_t args; /* operation arguments */
int rval; /* return value */
int v; /* type-checking value */
ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR);
if ((rval = xfs_dir_ino_validate(tp->t_mountp, inum))) {
return rval;
}
XFS_STATS_INC(xs_dir_create);
/*
* Fill in the arg structure for this request.
*/
args.name = name;
args.namelen = namelen;
args.hashval = xfs_da_hashname(name, namelen);
args.inumber = inum;
args.dp = dp;
args.firstblock = first;
args.flist = flist;
args.total = total;
args.whichfork = XFS_DATA_FORK;
args.trans = tp;
args.justcheck = 0;
args.addname = args.oknoent = 1;
/*
* Decide on what work routines to call based on the inode size.
*/
if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL)
rval = xfs_dir2_sf_addname(&args);
else if ((rval = xfs_dir2_isblock(tp, dp, &v))) {
return rval;
} else if (v)
rval = xfs_dir2_block_addname(&args);
else if ((rval = xfs_dir2_isleaf(tp, dp, &v))) {
return rval;
} else if (v)
rval = xfs_dir2_leaf_addname(&args);
else
rval = xfs_dir2_node_addname(&args);
return rval;
}
/*
* Lookup a name in a directory, give back the inode number.
*/
static int /* error */
xfs_dir2_lookup(
xfs_trans_t *tp, /* transaction pointer */
xfs_inode_t *dp, /* incore directory inode */
char *name, /* lookup name */
int namelen, /* lookup name length */
xfs_ino_t *inum) /* out: inode number */
{
xfs_da_args_t args; /* operation arguments */
int rval; /* return value */
int v; /* type-checking value */
ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR);
XFS_STATS_INC(xs_dir_lookup);
/*
* Fill in the arg structure for this request.
*/
args.name = name;
args.namelen = namelen;
args.hashval = xfs_da_hashname(name, namelen);
args.inumber = 0;
args.dp = dp;
args.firstblock = NULL;
args.flist = NULL;
args.total = 0;
args.whichfork = XFS_DATA_FORK;
args.trans = tp;
args.justcheck = args.addname = 0;
args.oknoent = 1;
/*
* Decide on what work routines to call based on the inode size.
*/
if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL)
rval = xfs_dir2_sf_lookup(&args);
else if ((rval = xfs_dir2_isblock(tp, dp, &v))) {
return rval;
} else if (v)
rval = xfs_dir2_block_lookup(&args);
else if ((rval = xfs_dir2_isleaf(tp, dp, &v))) {
return rval;
} else if (v)
rval = xfs_dir2_leaf_lookup(&args);
else
rval = xfs_dir2_node_lookup(&args);
if (rval == EEXIST)
rval = 0;
if (rval == 0)
*inum = args.inumber;
return rval;
}
/*
* Remove an entry from a directory.
*/
static int /* error */
xfs_dir2_removename(
xfs_trans_t *tp, /* transaction pointer */
xfs_inode_t *dp, /* incore directory inode */
char *name, /* name of entry to remove */
int namelen, /* name length of entry to remove */
xfs_ino_t ino, /* inode number of entry to remove */
xfs_fsblock_t *first, /* bmap's firstblock */
xfs_bmap_free_t *flist, /* bmap's freeblock list */
xfs_extlen_t total) /* bmap's total block count */
{
xfs_da_args_t args; /* operation arguments */
int rval; /* return value */
int v; /* type-checking value */
ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR);
XFS_STATS_INC(xs_dir_remove);
/*
* Fill in the arg structure for this request.
*/
args.name = name;
args.namelen = namelen;
args.hashval = xfs_da_hashname(name, namelen);
args.inumber = ino;
args.dp = dp;
args.firstblock = first;
args.flist = flist;
args.total = total;
args.whichfork = XFS_DATA_FORK;
args.trans = tp;
args.justcheck = args.addname = args.oknoent = 0;
/*
* Decide on what work routines to call based on the inode size.
*/
if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL)
rval = xfs_dir2_sf_removename(&args);
else if ((rval = xfs_dir2_isblock(tp, dp, &v))) {
return rval;
} else if (v)
rval = xfs_dir2_block_removename(&args);
else if ((rval = xfs_dir2_isleaf(tp, dp, &v))) {
return rval;
} else if (v)
rval = xfs_dir2_leaf_removename(&args);
else
rval = xfs_dir2_node_removename(&args);
return rval;
}
/*
* Read a directory.
*/
static int /* error */
xfs_dir2_getdents(
xfs_trans_t *tp, /* transaction pointer */
xfs_inode_t *dp, /* incore directory inode */
uio_t *uio, /* caller's buffer control */
int *eofp) /* out: eof reached */
{
int alignment; /* alignment required for ABI */
xfs_dirent_t *dbp; /* malloc'ed buffer */
xfs_dir2_put_t put; /* entry formatting routine */
int rval; /* return value */
int v; /* type-checking value */
ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR);
XFS_STATS_INC(xs_dir_getdents);
/*
* If our caller has given us a single contiguous aligned memory buffer,
* just work directly within that buffer. If it's in user memory,
* lock it down first.
*/
alignment = sizeof(xfs_off_t) - 1;
if ((uio->uio_iovcnt == 1) &&
(((__psint_t)uio->uio_iov[0].iov_base & alignment) == 0) &&
((uio->uio_iov[0].iov_len & alignment) == 0)) {
dbp = NULL;
put = xfs_dir2_put_dirent64_direct;
} else {
dbp = kmem_alloc(sizeof(*dbp) + MAXNAMELEN, KM_SLEEP);
put = xfs_dir2_put_dirent64_uio;
}
*eofp = 0;
/*
* Decide on what work routines to call based on the inode size.
*/
if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL)
rval = xfs_dir2_sf_getdents(dp, uio, eofp, dbp, put);
else if ((rval = xfs_dir2_isblock(tp, dp, &v))) {
;
} else if (v)
rval = xfs_dir2_block_getdents(tp, dp, uio, eofp, dbp, put);
else
rval = xfs_dir2_leaf_getdents(tp, dp, uio, eofp, dbp, put);
if (dbp != NULL)
kmem_free(dbp, sizeof(*dbp) + MAXNAMELEN);
return rval;
}
/*
* Replace the inode number of a directory entry.
*/
static int /* error */
xfs_dir2_replace(
xfs_trans_t *tp, /* transaction pointer */
xfs_inode_t *dp, /* incore directory inode */
char *name, /* name of entry to replace */
int namelen, /* name length of entry to replace */
xfs_ino_t inum, /* new inode number */
xfs_fsblock_t *first, /* bmap's firstblock */
xfs_bmap_free_t *flist, /* bmap's freeblock list */
xfs_extlen_t total) /* bmap's total block count */
{
xfs_da_args_t args; /* operation arguments */
int rval; /* return value */
int v; /* type-checking value */
ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR);
if ((rval = xfs_dir_ino_validate(tp->t_mountp, inum))) {
return rval;
}
/*
* Fill in the arg structure for this request.
*/
args.name = name;
args.namelen = namelen;
args.hashval = xfs_da_hashname(name, namelen);
args.inumber = inum;
args.dp = dp;
args.firstblock = first;
args.flist = flist;
args.total = total;
args.whichfork = XFS_DATA_FORK;
args.trans = tp;
args.justcheck = args.addname = args.oknoent = 0;
/*
* Decide on what work routines to call based on the inode size.
*/
if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL)
rval = xfs_dir2_sf_replace(&args);
else if ((rval = xfs_dir2_isblock(tp, dp, &v))) {
return rval;
} else if (v)
rval = xfs_dir2_block_replace(&args);
else if ((rval = xfs_dir2_isleaf(tp, dp, &v))) {
return rval;
} else if (v)
rval = xfs_dir2_leaf_replace(&args);
else
rval = xfs_dir2_node_replace(&args);
return rval;
}
/*
* See if this entry can be added to the directory without allocating space.
*/
static int /* error */
xfs_dir2_canenter(
xfs_trans_t *tp, /* transaction pointer */
xfs_inode_t *dp, /* incore directory inode */
char *name, /* name of entry to add */
int namelen) /* name length of entry to add */
{
xfs_da_args_t args; /* operation arguments */
int rval; /* return value */
int v; /* type-checking value */
ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR);
/*
* Fill in the arg structure for this request.
*/
args.name = name;
args.namelen = namelen;
args.hashval = xfs_da_hashname(name, namelen);
args.inumber = 0;
args.dp = dp;
args.firstblock = NULL;
args.flist = NULL;
args.total = 0;
args.whichfork = XFS_DATA_FORK;
args.trans = tp;
args.justcheck = args.addname = args.oknoent = 1;
/*
* Decide on what work routines to call based on the inode size.
*/
if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL)
rval = xfs_dir2_sf_addname(&args);
else if ((rval = xfs_dir2_isblock(tp, dp, &v))) {
return rval;
} else if (v)
rval = xfs_dir2_block_addname(&args);
else if ((rval = xfs_dir2_isleaf(tp, dp, &v))) {
return rval;
} else if (v)
rval = xfs_dir2_leaf_addname(&args);
else
rval = xfs_dir2_node_addname(&args);
return rval;
}
/*
* Dummy routine for shortform inode validation.
* Can't really do this.
*/
/* ARGSUSED */
static int /* error */
xfs_dir2_shortform_validate_ondisk(
xfs_mount_t *mp, /* filesystem mount point */
xfs_dinode_t *dip) /* ondisk inode */
{
return 0;
}
/*
* Utility routines.
*/
/*
* Add a block to the directory.
* This routine is for data and free blocks, not leaf/node blocks
* which are handled by xfs_da_grow_inode.
*/
int /* error */
xfs_dir2_grow_inode(
xfs_da_args_t *args, /* operation arguments */
int space, /* v2 dir's space XFS_DIR2_xxx_SPACE */
xfs_dir2_db_t *dbp) /* out: block number added */
{
xfs_fileoff_t bno; /* directory offset of new block */
int count; /* count of filesystem blocks */
xfs_inode_t *dp; /* incore directory inode */
int error; /* error return value */
int got; /* blocks actually mapped */
int i; /* temp mapping index */
xfs_bmbt_irec_t map; /* single structure for bmap */
int mapi; /* mapping index */
xfs_bmbt_irec_t *mapp; /* bmap mapping structure(s) */
xfs_mount_t *mp; /* filesystem mount point */
int nmap; /* number of bmap entries */
xfs_trans_t *tp; /* transaction pointer */
xfs_dir2_trace_args_s("grow_inode", args, space);
dp = args->dp;
tp = args->trans;
mp = dp->i_mount;
/*
* Set lowest possible block in the space requested.
*/
bno = XFS_B_TO_FSBT(mp, space * XFS_DIR2_SPACE_SIZE);
count = mp->m_dirblkfsbs;
/*
* Find the first hole for our block.
*/
if ((error = xfs_bmap_first_unused(tp, dp, count, &bno, XFS_DATA_FORK))) {
return error;
}
nmap = 1;
ASSERT(args->firstblock != NULL);
/*
* Try mapping the new block contiguously (one extent).
*/
if ((error = xfs_bmapi(tp, dp, bno, count,
XFS_BMAPI_WRITE|XFS_BMAPI_METADATA|XFS_BMAPI_CONTIG,
args->firstblock, args->total, &map, &nmap,
args->flist, NULL))) {
return error;
}
ASSERT(nmap <= 1);
/*
* Got it in 1.
*/
if (nmap == 1) {
mapp = &map;
mapi = 1;
}
/*
* Didn't work and this is a multiple-fsb directory block.
* Try again with contiguous flag turned on.
*/
else if (nmap == 0 && count > 1) {
xfs_fileoff_t b; /* current file offset */
/*
* Space for maximum number of mappings.
*/
mapp = kmem_alloc(sizeof(*mapp) * count, KM_SLEEP);
/*
* Iterate until we get to the end of our block.
*/
for (b = bno, mapi = 0; b < bno + count; ) {
int c; /* current fsb count */
/*
* Can't map more than MAX_NMAP at once.
*/
nmap = MIN(XFS_BMAP_MAX_NMAP, count);
c = (int)(bno + count - b);
if ((error = xfs_bmapi(tp, dp, b, c,
XFS_BMAPI_WRITE|XFS_BMAPI_METADATA,
args->firstblock, args->total,
&mapp[mapi], &nmap, args->flist,
NULL))) {
kmem_free(mapp, sizeof(*mapp) * count);
return error;
}
if (nmap < 1)
break;
/*
* Add this bunch into our table, go to the next offset.
*/
mapi += nmap;
b = mapp[mapi - 1].br_startoff +
mapp[mapi - 1].br_blockcount;
}
}
/*
* Didn't work.
*/
else {
mapi = 0;
mapp = NULL;
}
/*
* See how many fsb's we got.
*/
for (i = 0, got = 0; i < mapi; i++)
got += mapp[i].br_blockcount;
/*
* Didn't get enough fsb's, or the first/last block's are wrong.
*/
if (got != count || mapp[0].br_startoff != bno ||
mapp[mapi - 1].br_startoff + mapp[mapi - 1].br_blockcount !=
bno + count) {
if (mapp != &map)
kmem_free(mapp, sizeof(*mapp) * count);
return XFS_ERROR(ENOSPC);
}
/*
* Done with the temporary mapping table.
*/
if (mapp != &map)
kmem_free(mapp, sizeof(*mapp) * count);
*dbp = XFS_DIR2_DA_TO_DB(mp, (xfs_dablk_t)bno);
/*
* Update file's size if this is the data space and it grew.
*/
if (space == XFS_DIR2_DATA_SPACE) {
xfs_fsize_t size; /* directory file (data) size */
size = XFS_FSB_TO_B(mp, bno + count);
if (size > dp->i_d.di_size) {
dp->i_d.di_size = size;
xfs_trans_log_inode(tp, dp, XFS_ILOG_CORE);
}
}
return 0;
}
/*
* See if the directory is a single-block form directory.
*/
int /* error */
xfs_dir2_isblock(
xfs_trans_t *tp, /* transaction pointer */
xfs_inode_t *dp, /* incore directory inode */
int *vp) /* out: 1 is block, 0 is not block */
{
xfs_fileoff_t last; /* last file offset */
xfs_mount_t *mp; /* filesystem mount point */
int rval; /* return value */
mp = dp->i_mount;
if ((rval = xfs_bmap_last_offset(tp, dp, &last, XFS_DATA_FORK))) {
return rval;
}
rval = XFS_FSB_TO_B(mp, last) == mp->m_dirblksize;
ASSERT(rval == 0 || dp->i_d.di_size == mp->m_dirblksize);
*vp = rval;
return 0;
}
/*
* See if the directory is a single-leaf form directory.
*/
int /* error */
xfs_dir2_isleaf(
xfs_trans_t *tp, /* transaction pointer */
xfs_inode_t *dp, /* incore directory inode */
int *vp) /* out: 1 is leaf, 0 is not leaf */
{
xfs_fileoff_t last; /* last file offset */
xfs_mount_t *mp; /* filesystem mount point */
int rval; /* return value */
mp = dp->i_mount;
if ((rval = xfs_bmap_last_offset(tp, dp, &last, XFS_DATA_FORK))) {
return rval;
}
*vp = last == mp->m_dirleafblk + (1 << mp->m_sb.sb_dirblklog);
return 0;
}
/*
* Getdents put routine for 64-bit ABI, direct form.
*/
static int /* error */
xfs_dir2_put_dirent64_direct(
xfs_dir2_put_args_t *pa) /* argument bundle */
{
struct dirent *idbp, dtmp; /* dirent pointer */
iovec_t *iovp; /* io vector */
int namelen; /* entry name length */
int reclen; /* entry total length */
uio_t *uio; /* I/O control */
namelen = pa->namelen;
dtmp.d_namlen = namelen;
dtmp.d_reclen = GENERIC_DIRSIZ(&dtmp);
reclen = dtmp.d_reclen;
uio = pa->uio;
/*
* Won't fit in the remaining space.
*/
if (reclen > uio->uio_resid) {
pa->done = 0;
return 0;
}
iovp = uio->uio_iov;
idbp = (struct dirent *)iovp->iov_base;
iovp->iov_base = (char *)idbp + reclen;
iovp->iov_len -= reclen;
uio->uio_resid -= reclen;
idbp->d_reclen = reclen;
idbp->d_fileno = pa->ino;
idbp->d_type = DT_UNKNOWN;
idbp->d_namlen = namelen;
memcpy(idbp->d_name, pa->name, namelen);
idbp->d_name[namelen] = '\0';
pa->done = 1;
return 0;
}
/*
* Getdents put routine for 64-bit ABI, uio form.
*/
static int /* error */
xfs_dir2_put_dirent64_uio(
xfs_dir2_put_args_t *pa) /* argument bundle */
{
struct dirent *idbp, dtmp; /* dirent pointer */
int namelen; /* entry name length */
int reclen; /* entry total length */
int rval; /* return value */
uio_t *uio; /* I/O control */
namelen = pa->namelen;
dtmp.d_namlen = namelen;
dtmp.d_reclen = GENERIC_DIRSIZ(&dtmp);
reclen = dtmp.d_reclen;
uio = pa->uio;
/*
* Won't fit in the remaining space.
*/
if (reclen > uio->uio_resid) {
pa->done = 0;
return 0;
}
idbp = &dtmp;
idbp->d_reclen = reclen;
idbp->d_fileno = pa->ino;
idbp->d_type = DT_UNKNOWN;
idbp->d_namlen = namelen;
memcpy(idbp->d_name, pa->name, namelen);
idbp->d_name[namelen] = '\0';
rval = uio_read((caddr_t)idbp, reclen, uio);
pa->done = (rval == 0);
return rval;
}
/*
* Remove the given block from the directory.
* This routine is used for data and free blocks, leaf/node are done
* by xfs_da_shrink_inode.
*/
int
xfs_dir2_shrink_inode(
xfs_da_args_t *args, /* operation arguments */
xfs_dir2_db_t db, /* directory block number */
xfs_dabuf_t *bp) /* block's buffer */
{
xfs_fileoff_t bno; /* directory file offset */
xfs_dablk_t da; /* directory file offset */
int done; /* bunmap is finished */
xfs_inode_t *dp; /* incore directory inode */
int error; /* error return value */
xfs_mount_t *mp; /* filesystem mount point */
xfs_trans_t *tp; /* transaction pointer */
xfs_dir2_trace_args_db("shrink_inode", args, db, bp);
dp = args->dp;
mp = dp->i_mount;
tp = args->trans;
da = XFS_DIR2_DB_TO_DA(mp, db);
/*
* Unmap the fsblock(s).
*/
if ((error = xfs_bunmapi(tp, dp, da, mp->m_dirblkfsbs,
XFS_BMAPI_METADATA, 0, args->firstblock, args->flist,
NULL, &done))) {
/*
* ENOSPC actually can happen if we're in a removename with
* no space reservation, and the resulting block removal
* would cause a bmap btree split or conversion from extents
* to btree. This can only happen for un-fragmented
* directory blocks, since you need to be punching out
* the middle of an extent.
* In this case we need to leave the block in the file,
* and not binval it.
* So the block has to be in a consistent empty state
* and appropriately logged.
* We don't free up the buffer, the caller can tell it
* hasn't happened since it got an error back.
*/
return error;
}
ASSERT(done);
/*
* Invalidate the buffer from the transaction.
*/
xfs_da_binval(tp, bp);
/*
* If it's not a data block, we're done.
*/
if (db >= XFS_DIR2_LEAF_FIRSTDB(mp))
return 0;
/*
* If the block isn't the last one in the directory, we're done.
*/
if (dp->i_d.di_size > XFS_DIR2_DB_OFF_TO_BYTE(mp, db + 1, 0))
return 0;
bno = da;
if ((error = xfs_bmap_last_before(tp, dp, &bno, XFS_DATA_FORK))) {
/*
* This can't really happen unless there's kernel corruption.
*/
return error;
}
if (db == mp->m_dirdatablk)
ASSERT(bno == 0);
else
ASSERT(bno > 0);
/*
* Set the size to the new last block.
*/
dp->i_d.di_size = XFS_FSB_TO_B(mp, bno);
xfs_trans_log_inode(tp, dp, XFS_ILOG_CORE);
return 0;
}

View File

@ -1,87 +0,0 @@
/*
* Copyright (c) 2000-2001,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
*/
#ifndef __XFS_DIR2_H__
#define __XFS_DIR2_H__
struct uio;
struct xfs_dabuf;
struct xfs_da_args;
struct xfs_dir2_put_args;
struct xfs_inode;
struct xfs_trans;
/*
* Directory version 2.
* There are 4 possible formats:
* shortform
* single block - data with embedded leaf at the end
* multiple data blocks, single leaf+freeindex block
* data blocks, node&leaf blocks (btree), freeindex blocks
*
* The shortform format is in xfs_dir2_sf.h.
* The single block format is in xfs_dir2_block.h.
* The data block format is in xfs_dir2_data.h.
* The leaf and freeindex block formats are in xfs_dir2_leaf.h.
* Node blocks are the same as the other version, in xfs_da_btree.h.
*/
/*
* Byte offset in data block and shortform entry.
*/
typedef __uint16_t xfs_dir2_data_off_t;
#define NULLDATAOFF 0xffffU
typedef uint xfs_dir2_data_aoff_t; /* argument form */
/*
* Directory block number (logical dirblk in file)
*/
typedef __uint32_t xfs_dir2_db_t;
/*
* Byte offset in a directory.
*/
typedef xfs_off_t xfs_dir2_off_t;
/*
* For getdents, argument struct for put routines.
*/
typedef int (*xfs_dir2_put_t)(struct xfs_dir2_put_args *pa);
typedef struct xfs_dir2_put_args {
xfs_off_t cook; /* cookie of (next) entry */
xfs_intino_t ino; /* inode number */
xfs_dirent_t *dbp; /* buffer pointer */
char *name; /* directory entry name */
int namelen; /* length of name */
int done; /* output: set if value was stored */
xfs_dir2_put_t put; /* put function ptr (i/o) */
struct uio *uio; /* uio control structure */
} xfs_dir2_put_args_t;
/*
* Other interfaces used by the rest of the dir v2 code.
*/
extern int xfs_dir2_grow_inode(struct xfs_da_args *args, int space,
xfs_dir2_db_t *dbp);
extern int xfs_dir2_isblock(struct xfs_trans *tp, struct xfs_inode *dp,
int *vp);
extern int xfs_dir2_isleaf(struct xfs_trans *tp, struct xfs_inode *dp,
int *vp);
extern int xfs_dir2_shrink_inode(struct xfs_da_args *args, xfs_dir2_db_t db,
struct xfs_dabuf *bp);
#endif /* __XFS_DIR2_H__ */

File diff suppressed because it is too large Load Diff

View File

@ -1,95 +0,0 @@
/*
* Copyright (c) 2000-2001,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
*/
#ifndef __XFS_DIR2_BLOCK_H__
#define __XFS_DIR2_BLOCK_H__
/*
* xfs_dir2_block.h
* Directory version 2, single block format structures
*/
struct uio;
struct xfs_dabuf;
struct xfs_da_args;
struct xfs_dir2_data_hdr;
struct xfs_dir2_leaf_entry;
struct xfs_inode;
struct xfs_mount;
struct xfs_trans;
/*
* The single block format is as follows:
* xfs_dir2_data_hdr_t structure
* xfs_dir2_data_entry_t and xfs_dir2_data_unused_t structures
* xfs_dir2_leaf_entry_t structures
* xfs_dir2_block_tail_t structure
*/
#define XFS_DIR2_BLOCK_MAGIC 0x58443242 /* XD2B: for one block dirs */
typedef struct xfs_dir2_block_tail {
__be32 count; /* count of leaf entries */
__be32 stale; /* count of stale lf entries */
} xfs_dir2_block_tail_t;
/*
* Generic single-block structure, for xfs_db.
*/
typedef struct xfs_dir2_block {
xfs_dir2_data_hdr_t hdr; /* magic XFS_DIR2_BLOCK_MAGIC */
xfs_dir2_data_union_t u[1];
xfs_dir2_leaf_entry_t leaf[1];
xfs_dir2_block_tail_t tail;
} xfs_dir2_block_t;
/*
* Pointer to the leaf header embedded in a data block (1-block format)
*/
#define XFS_DIR2_BLOCK_TAIL_P(mp,block) xfs_dir2_block_tail_p(mp,block)
static inline xfs_dir2_block_tail_t *
xfs_dir2_block_tail_p(struct xfs_mount *mp, xfs_dir2_block_t *block)
{
return (((xfs_dir2_block_tail_t *)
((char *)(block) + (mp)->m_dirblksize)) - 1);
}
/*
* Pointer to the leaf entries embedded in a data block (1-block format)
*/
#define XFS_DIR2_BLOCK_LEAF_P(btp) xfs_dir2_block_leaf_p(btp)
static inline struct xfs_dir2_leaf_entry *
xfs_dir2_block_leaf_p(xfs_dir2_block_tail_t *btp)
{
return ((struct xfs_dir2_leaf_entry *)btp) - be32_to_cpu(btp->count);
}
/*
* Function declarations.
*/
extern int xfs_dir2_block_addname(struct xfs_da_args *args);
extern int xfs_dir2_block_getdents(struct xfs_trans *tp, struct xfs_inode *dp,
struct uio *uio, int *eofp,
struct xfs_dirent *dbp, xfs_dir2_put_t put);
extern int xfs_dir2_block_lookup(struct xfs_da_args *args);
extern int xfs_dir2_block_removename(struct xfs_da_args *args);
extern int xfs_dir2_block_replace(struct xfs_da_args *args);
extern int xfs_dir2_leaf_to_block(struct xfs_da_args *args,
struct xfs_dabuf *lbp, struct xfs_dabuf *dbp);
extern int xfs_dir2_sf_to_block(struct xfs_da_args *args);
#endif /* __XFS_DIR2_BLOCK_H__ */

View File

@ -1,837 +0,0 @@
/*
* Copyright (c) 2000-2002,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"
#include "xfs_fs.h"
#include "xfs_types.h"
#include "xfs_log.h"
#include "xfs_inum.h"
#include "xfs_trans.h"
#include "xfs_sb.h"
#include "xfs_dir.h"
#include "xfs_dir2.h"
#include "xfs_dmapi.h"
#include "xfs_mount.h"
#include "xfs_da_btree.h"
#include "xfs_bmap_btree.h"
#include "xfs_dir_sf.h"
#include "xfs_dir2_sf.h"
#include "xfs_attr_sf.h"
#include "xfs_dinode.h"
#include "xfs_inode.h"
#include "xfs_dir_leaf.h"
#include "xfs_dir2_data.h"
#include "xfs_dir2_leaf.h"
#include "xfs_dir2_block.h"
#include "xfs_error.h"
#ifdef DEBUG
/*
* Check the consistency of the data block.
* The input can also be a block-format directory.
* Pop an assert if we find anything bad.
*/
void
xfs_dir2_data_check(
xfs_inode_t *dp, /* incore inode pointer */
xfs_dabuf_t *bp) /* data block's buffer */
{
xfs_dir2_dataptr_t addr; /* addr for leaf lookup */
xfs_dir2_data_free_t *bf; /* bestfree table */
xfs_dir2_block_tail_t *btp=NULL; /* block tail */
int count; /* count of entries found */
xfs_dir2_data_t *d; /* data block pointer */
xfs_dir2_data_entry_t *dep; /* data entry */
xfs_dir2_data_free_t *dfp; /* bestfree entry */
xfs_dir2_data_unused_t *dup; /* unused entry */
char *endp; /* end of useful data */
int freeseen; /* mask of bestfrees seen */
xfs_dahash_t hash; /* hash of current name */
int i; /* leaf index */
int lastfree; /* last entry was unused */
xfs_dir2_leaf_entry_t *lep=NULL; /* block leaf entries */
xfs_mount_t *mp; /* filesystem mount point */
char *p; /* current data position */
int stale; /* count of stale leaves */
mp = dp->i_mount;
d = bp->data;
ASSERT(be32_to_cpu(d->hdr.magic) == XFS_DIR2_DATA_MAGIC ||
be32_to_cpu(d->hdr.magic) == XFS_DIR2_BLOCK_MAGIC);
bf = d->hdr.bestfree;
p = (char *)d->u;
if (be32_to_cpu(d->hdr.magic) == XFS_DIR2_BLOCK_MAGIC) {
btp = XFS_DIR2_BLOCK_TAIL_P(mp, (xfs_dir2_block_t *)d);
lep = XFS_DIR2_BLOCK_LEAF_P(btp);
endp = (char *)lep;
} else
endp = (char *)d + mp->m_dirblksize;
count = lastfree = freeseen = 0;
/*
* Account for zero bestfree entries.
*/
if (!bf[0].length) {
ASSERT(!bf[0].offset);
freeseen |= 1 << 0;
}
if (!bf[1].length) {
ASSERT(!bf[1].offset);
freeseen |= 1 << 1;
}
if (!bf[2].length) {
ASSERT(!bf[2].offset);
freeseen |= 1 << 2;
}
ASSERT(be16_to_cpu(bf[0].length) >= be16_to_cpu(bf[1].length));
ASSERT(be16_to_cpu(bf[1].length) >= be16_to_cpu(bf[2].length));
/*
* Loop over the data/unused entries.
*/
while (p < endp) {
dup = (xfs_dir2_data_unused_t *)p;
/*
* If it's unused, look for the space in the bestfree table.
* If we find it, account for that, else make sure it
* doesn't need to be there.
*/
if (be16_to_cpu(dup->freetag) == XFS_DIR2_DATA_FREE_TAG) {
ASSERT(lastfree == 0);
ASSERT(be16_to_cpu(*XFS_DIR2_DATA_UNUSED_TAG_P(dup)) ==
(char *)dup - (char *)d);
dfp = xfs_dir2_data_freefind(d, dup);
if (dfp) {
i = (int)(dfp - bf);
ASSERT((freeseen & (1 << i)) == 0);
freeseen |= 1 << i;
} else {
ASSERT(be16_to_cpu(dup->length) <=
be16_to_cpu(bf[2].length));
}
p += be16_to_cpu(dup->length);
lastfree = 1;
continue;
}
/*
* It's a real entry. Validate the fields.
* If this is a block directory then make sure it's
* in the leaf section of the block.
* The linear search is crude but this is DEBUG code.
*/
dep = (xfs_dir2_data_entry_t *)p;
ASSERT(dep->namelen != 0);
ASSERT(xfs_dir_ino_validate(mp, INT_GET(dep->inumber, ARCH_CONVERT)) == 0);
ASSERT(be16_to_cpu(*XFS_DIR2_DATA_ENTRY_TAG_P(dep)) ==
(char *)dep - (char *)d);
count++;
lastfree = 0;
if (be32_to_cpu(d->hdr.magic) == XFS_DIR2_BLOCK_MAGIC) {
addr = XFS_DIR2_DB_OFF_TO_DATAPTR(mp, mp->m_dirdatablk,
(xfs_dir2_data_aoff_t)
((char *)dep - (char *)d));
hash = xfs_da_hashname((char *)dep->name, dep->namelen);
for (i = 0; i < be32_to_cpu(btp->count); i++) {
if (be32_to_cpu(lep[i].address) == addr &&
be32_to_cpu(lep[i].hashval) == hash)
break;
}
ASSERT(i < be32_to_cpu(btp->count));
}
p += XFS_DIR2_DATA_ENTSIZE(dep->namelen);
}
/*
* Need to have seen all the entries and all the bestfree slots.
*/
ASSERT(freeseen == 7);
if (be32_to_cpu(d->hdr.magic) == XFS_DIR2_BLOCK_MAGIC) {
for (i = stale = 0; i < be32_to_cpu(btp->count); i++) {
if (be32_to_cpu(lep[i].address) == XFS_DIR2_NULL_DATAPTR)
stale++;
if (i > 0)
ASSERT(be32_to_cpu(lep[i].hashval) >= be32_to_cpu(lep[i - 1].hashval));
}
ASSERT(count == be32_to_cpu(btp->count) - be32_to_cpu(btp->stale));
ASSERT(stale == be32_to_cpu(btp->stale));
}
}
#endif
/*
* Given a data block and an unused entry from that block,
* return the bestfree entry if any that corresponds to it.
*/
xfs_dir2_data_free_t *
xfs_dir2_data_freefind(
xfs_dir2_data_t *d, /* data block */
xfs_dir2_data_unused_t *dup) /* data unused entry */
{
xfs_dir2_data_free_t *dfp; /* bestfree entry */
xfs_dir2_data_aoff_t off; /* offset value needed */
#if defined(DEBUG) && defined(__KERNEL__)
int matched; /* matched the value */
int seenzero; /* saw a 0 bestfree entry */
#endif
off = (xfs_dir2_data_aoff_t)((char *)dup - (char *)d);
#if defined(DEBUG) && defined(__KERNEL__)
/*
* Validate some consistency in the bestfree table.
* Check order, non-overlapping entries, and if we find the
* one we're looking for it has to be exact.
*/
ASSERT(be32_to_cpu(d->hdr.magic) == XFS_DIR2_DATA_MAGIC ||
be32_to_cpu(d->hdr.magic) == XFS_DIR2_BLOCK_MAGIC);
for (dfp = &d->hdr.bestfree[0], seenzero = matched = 0;
dfp < &d->hdr.bestfree[XFS_DIR2_DATA_FD_COUNT];
dfp++) {
if (!dfp->offset) {
ASSERT(!dfp->length);
seenzero = 1;
continue;
}
ASSERT(seenzero == 0);
if (be16_to_cpu(dfp->offset) == off) {
matched = 1;
ASSERT(dfp->length == dup->length);
} else if (off < be16_to_cpu(dfp->offset))
ASSERT(off + be16_to_cpu(dup->length) <= be16_to_cpu(dfp->offset));
else
ASSERT(be16_to_cpu(dfp->offset) + be16_to_cpu(dfp->length) <= off);
ASSERT(matched || be16_to_cpu(dfp->length) >= be16_to_cpu(dup->length));
if (dfp > &d->hdr.bestfree[0])
ASSERT(be16_to_cpu(dfp[-1].length) >= be16_to_cpu(dfp[0].length));
}
#endif
/*
* If this is smaller than the smallest bestfree entry,
* it can't be there since they're sorted.
*/
if (be16_to_cpu(dup->length) <
be16_to_cpu(d->hdr.bestfree[XFS_DIR2_DATA_FD_COUNT - 1].length))
return NULL;
/*
* Look at the three bestfree entries for our guy.
*/
for (dfp = &d->hdr.bestfree[0];
dfp < &d->hdr.bestfree[XFS_DIR2_DATA_FD_COUNT];
dfp++) {
if (!dfp->offset)
return NULL;
if (be16_to_cpu(dfp->offset) == off)
return dfp;
}
/*
* Didn't find it. This only happens if there are duplicate lengths.
*/
return NULL;
}
/*
* Insert an unused-space entry into the bestfree table.
*/
xfs_dir2_data_free_t * /* entry inserted */
xfs_dir2_data_freeinsert(
xfs_dir2_data_t *d, /* data block pointer */
xfs_dir2_data_unused_t *dup, /* unused space */
int *loghead) /* log the data header (out) */
{
xfs_dir2_data_free_t *dfp; /* bestfree table pointer */
xfs_dir2_data_free_t new; /* new bestfree entry */
#ifdef __KERNEL__
ASSERT(be32_to_cpu(d->hdr.magic) == XFS_DIR2_DATA_MAGIC ||
be32_to_cpu(d->hdr.magic) == XFS_DIR2_BLOCK_MAGIC);
#endif
dfp = d->hdr.bestfree;
new.length = dup->length;
new.offset = cpu_to_be16((char *)dup - (char *)d);
/*
* Insert at position 0, 1, or 2; or not at all.
*/
if (be16_to_cpu(new.length) > be16_to_cpu(dfp[0].length)) {
dfp[2] = dfp[1];
dfp[1] = dfp[0];
dfp[0] = new;
*loghead = 1;
return &dfp[0];
}
if (be16_to_cpu(new.length) > be16_to_cpu(dfp[1].length)) {
dfp[2] = dfp[1];
dfp[1] = new;
*loghead = 1;
return &dfp[1];
}
if (be16_to_cpu(new.length) > be16_to_cpu(dfp[2].length)) {
dfp[2] = new;
*loghead = 1;
return &dfp[2];
}
return NULL;
}
/*
* Remove a bestfree entry from the table.
*/
STATIC void
xfs_dir2_data_freeremove(
xfs_dir2_data_t *d, /* data block pointer */
xfs_dir2_data_free_t *dfp, /* bestfree entry pointer */
int *loghead) /* out: log data header */
{
#ifdef __KERNEL__
ASSERT(be32_to_cpu(d->hdr.magic) == XFS_DIR2_DATA_MAGIC ||
be32_to_cpu(d->hdr.magic) == XFS_DIR2_BLOCK_MAGIC);
#endif
/*
* It's the first entry, slide the next 2 up.
*/
if (dfp == &d->hdr.bestfree[0]) {
d->hdr.bestfree[0] = d->hdr.bestfree[1];
d->hdr.bestfree[1] = d->hdr.bestfree[2];
}
/*
* It's the second entry, slide the 3rd entry up.
*/
else if (dfp == &d->hdr.bestfree[1])
d->hdr.bestfree[1] = d->hdr.bestfree[2];
/*
* Must be the last entry.
*/
else
ASSERT(dfp == &d->hdr.bestfree[2]);
/*
* Clear the 3rd entry, must be zero now.
*/
d->hdr.bestfree[2].length = 0;
d->hdr.bestfree[2].offset = 0;
*loghead = 1;
}
/*
* Given a data block, reconstruct its bestfree map.
*/
void
xfs_dir2_data_freescan(
xfs_mount_t *mp, /* filesystem mount point */
xfs_dir2_data_t *d, /* data block pointer */
int *loghead, /* out: log data header */
char *aendp) /* in: caller's endp */
{
xfs_dir2_block_tail_t *btp; /* block tail */
xfs_dir2_data_entry_t *dep; /* active data entry */
xfs_dir2_data_unused_t *dup; /* unused data entry */
char *endp; /* end of block's data */
char *p; /* current entry pointer */
#ifdef __KERNEL__
ASSERT(be32_to_cpu(d->hdr.magic) == XFS_DIR2_DATA_MAGIC ||
be32_to_cpu(d->hdr.magic) == XFS_DIR2_BLOCK_MAGIC);
#endif
/*
* Start by clearing the table.
*/
memset(d->hdr.bestfree, 0, sizeof(d->hdr.bestfree));
*loghead = 1;
/*
* Set up pointers.
*/
p = (char *)d->u;
if (aendp)
endp = aendp;
else if (be32_to_cpu(d->hdr.magic) == XFS_DIR2_BLOCK_MAGIC) {
btp = XFS_DIR2_BLOCK_TAIL_P(mp, (xfs_dir2_block_t *)d);
endp = (char *)XFS_DIR2_BLOCK_LEAF_P(btp);
} else
endp = (char *)d + mp->m_dirblksize;
/*
* Loop over the block's entries.
*/
while (p < endp) {
dup = (xfs_dir2_data_unused_t *)p;
/*
* If it's a free entry, insert it.
*/
if (be16_to_cpu(dup->freetag) == XFS_DIR2_DATA_FREE_TAG) {
ASSERT((char *)dup - (char *)d ==
be16_to_cpu(*XFS_DIR2_DATA_UNUSED_TAG_P(dup)));
xfs_dir2_data_freeinsert(d, dup, loghead);
p += be16_to_cpu(dup->length);
}
/*
* For active entries, check their tags and skip them.
*/
else {
dep = (xfs_dir2_data_entry_t *)p;
ASSERT((char *)dep - (char *)d ==
be16_to_cpu(*XFS_DIR2_DATA_ENTRY_TAG_P(dep)));
p += XFS_DIR2_DATA_ENTSIZE(dep->namelen);
}
}
}
/*
* Initialize a data block at the given block number in the directory.
* Give back the buffer for the created block.
*/
int /* error */
xfs_dir2_data_init(
xfs_da_args_t *args, /* directory operation args */
xfs_dir2_db_t blkno, /* logical dir block number */
xfs_dabuf_t **bpp) /* output block buffer */
{
xfs_dabuf_t *bp; /* block buffer */
xfs_dir2_data_t *d; /* pointer to block */
xfs_inode_t *dp; /* incore directory inode */
xfs_dir2_data_unused_t *dup; /* unused entry pointer */
int error; /* error return value */
int i; /* bestfree index */
xfs_mount_t *mp; /* filesystem mount point */
xfs_trans_t *tp; /* transaction pointer */
int t; /* temp */
dp = args->dp;
mp = dp->i_mount;
tp = args->trans;
/*
* Get the buffer set up for the block.
*/
error = xfs_da_get_buf(tp, dp, XFS_DIR2_DB_TO_DA(mp, blkno), -1, &bp,
XFS_DATA_FORK);
if (error) {
return error;
}
ASSERT(bp != NULL);
/*
* Initialize the header.
*/
d = bp->data;
d->hdr.magic = cpu_to_be32(XFS_DIR2_DATA_MAGIC);
d->hdr.bestfree[0].offset = cpu_to_be16(sizeof(d->hdr));
for (i = 1; i < XFS_DIR2_DATA_FD_COUNT; i++) {
d->hdr.bestfree[i].length = 0;
d->hdr.bestfree[i].offset = 0;
}
/*
* Set up an unused entry for the block's body.
*/
dup = &d->u[0].unused;
dup->freetag = cpu_to_be16(XFS_DIR2_DATA_FREE_TAG);
t=mp->m_dirblksize - (uint)sizeof(d->hdr);
d->hdr.bestfree[0].length = cpu_to_be16(t);
dup->length = cpu_to_be16(t);
*XFS_DIR2_DATA_UNUSED_TAG_P(dup) = cpu_to_be16((char *)dup - (char *)d);
/*
* Log it and return it.
*/
xfs_dir2_data_log_header(tp, bp);
xfs_dir2_data_log_unused(tp, bp, dup);
*bpp = bp;
return 0;
}
/*
* Log an active data entry from the block.
*/
void
xfs_dir2_data_log_entry(
xfs_trans_t *tp, /* transaction pointer */
xfs_dabuf_t *bp, /* block buffer */
xfs_dir2_data_entry_t *dep) /* data entry pointer */
{
xfs_dir2_data_t *d; /* data block pointer */
d = bp->data;
ASSERT(be32_to_cpu(d->hdr.magic) == XFS_DIR2_DATA_MAGIC ||
be32_to_cpu(d->hdr.magic) == XFS_DIR2_BLOCK_MAGIC);
xfs_da_log_buf(tp, bp, (uint)((char *)dep - (char *)d),
(uint)((char *)(XFS_DIR2_DATA_ENTRY_TAG_P(dep) + 1) -
(char *)d - 1));
}
/*
* Log a data block header.
*/
void
xfs_dir2_data_log_header(
xfs_trans_t *tp, /* transaction pointer */
xfs_dabuf_t *bp) /* block buffer */
{
xfs_dir2_data_t *d; /* data block pointer */
d = bp->data;
ASSERT(be32_to_cpu(d->hdr.magic) == XFS_DIR2_DATA_MAGIC ||
be32_to_cpu(d->hdr.magic) == XFS_DIR2_BLOCK_MAGIC);
xfs_da_log_buf(tp, bp, (uint)((char *)&d->hdr - (char *)d),
(uint)(sizeof(d->hdr) - 1));
}
/*
* Log a data unused entry.
*/
void
xfs_dir2_data_log_unused(
xfs_trans_t *tp, /* transaction pointer */
xfs_dabuf_t *bp, /* block buffer */
xfs_dir2_data_unused_t *dup) /* data unused pointer */
{
xfs_dir2_data_t *d; /* data block pointer */
d = bp->data;
ASSERT(be32_to_cpu(d->hdr.magic) == XFS_DIR2_DATA_MAGIC ||
be32_to_cpu(d->hdr.magic) == XFS_DIR2_BLOCK_MAGIC);
/*
* Log the first part of the unused entry.
*/
xfs_da_log_buf(tp, bp, (uint)((char *)dup - (char *)d),
(uint)((char *)&dup->length + sizeof(dup->length) -
1 - (char *)d));
/*
* Log the end (tag) of the unused entry.
*/
xfs_da_log_buf(tp, bp,
(uint)((char *)XFS_DIR2_DATA_UNUSED_TAG_P(dup) - (char *)d),
(uint)((char *)XFS_DIR2_DATA_UNUSED_TAG_P(dup) - (char *)d +
sizeof(xfs_dir2_data_off_t) - 1));
}
/*
* Make a byte range in the data block unused.
* Its current contents are unimportant.
*/
void
xfs_dir2_data_make_free(
xfs_trans_t *tp, /* transaction pointer */
xfs_dabuf_t *bp, /* block buffer */
xfs_dir2_data_aoff_t offset, /* starting byte offset */
xfs_dir2_data_aoff_t len, /* length in bytes */
int *needlogp, /* out: log header */
int *needscanp) /* out: regen bestfree */
{
xfs_dir2_data_t *d; /* data block pointer */
xfs_dir2_data_free_t *dfp; /* bestfree pointer */
char *endptr; /* end of data area */
xfs_mount_t *mp; /* filesystem mount point */
int needscan; /* need to regen bestfree */
xfs_dir2_data_unused_t *newdup; /* new unused entry */
xfs_dir2_data_unused_t *postdup; /* unused entry after us */
xfs_dir2_data_unused_t *prevdup; /* unused entry before us */
mp = tp->t_mountp;
d = bp->data;
/*
* Figure out where the end of the data area is.
*/
if (be32_to_cpu(d->hdr.magic) == XFS_DIR2_DATA_MAGIC)
endptr = (char *)d + mp->m_dirblksize;
else {
xfs_dir2_block_tail_t *btp; /* block tail */
ASSERT(be32_to_cpu(d->hdr.magic) == XFS_DIR2_BLOCK_MAGIC);
btp = XFS_DIR2_BLOCK_TAIL_P(mp, (xfs_dir2_block_t *)d);
endptr = (char *)XFS_DIR2_BLOCK_LEAF_P(btp);
}
/*
* If this isn't the start of the block, then back up to
* the previous entry and see if it's free.
*/
if (offset > sizeof(d->hdr)) {
__be16 *tagp; /* tag just before us */
tagp = (__be16 *)((char *)d + offset) - 1;
prevdup = (xfs_dir2_data_unused_t *)((char *)d + be16_to_cpu(*tagp));
if (be16_to_cpu(prevdup->freetag) != XFS_DIR2_DATA_FREE_TAG)
prevdup = NULL;
} else
prevdup = NULL;
/*
* If this isn't the end of the block, see if the entry after
* us is free.
*/
if ((char *)d + offset + len < endptr) {
postdup =
(xfs_dir2_data_unused_t *)((char *)d + offset + len);
if (be16_to_cpu(postdup->freetag) != XFS_DIR2_DATA_FREE_TAG)
postdup = NULL;
} else
postdup = NULL;
ASSERT(*needscanp == 0);
needscan = 0;
/*
* Previous and following entries are both free,
* merge everything into a single free entry.
*/
if (prevdup && postdup) {
xfs_dir2_data_free_t *dfp2; /* another bestfree pointer */
/*
* See if prevdup and/or postdup are in bestfree table.
*/
dfp = xfs_dir2_data_freefind(d, prevdup);
dfp2 = xfs_dir2_data_freefind(d, postdup);
/*
* We need a rescan unless there are exactly 2 free entries
* namely our two. Then we know what's happening, otherwise
* since the third bestfree is there, there might be more
* entries.
*/
needscan = (d->hdr.bestfree[2].length != 0);
/*
* Fix up the new big freespace.
*/
be16_add(&prevdup->length, len + be16_to_cpu(postdup->length));
*XFS_DIR2_DATA_UNUSED_TAG_P(prevdup) =
cpu_to_be16((char *)prevdup - (char *)d);
xfs_dir2_data_log_unused(tp, bp, prevdup);
if (!needscan) {
/*
* Has to be the case that entries 0 and 1 are
* dfp and dfp2 (don't know which is which), and
* entry 2 is empty.
* Remove entry 1 first then entry 0.
*/
ASSERT(dfp && dfp2);
if (dfp == &d->hdr.bestfree[1]) {
dfp = &d->hdr.bestfree[0];
ASSERT(dfp2 == dfp);
dfp2 = &d->hdr.bestfree[1];
}
xfs_dir2_data_freeremove(d, dfp2, needlogp);
xfs_dir2_data_freeremove(d, dfp, needlogp);
/*
* Now insert the new entry.
*/
dfp = xfs_dir2_data_freeinsert(d, prevdup, needlogp);
ASSERT(dfp == &d->hdr.bestfree[0]);
ASSERT(dfp->length == prevdup->length);
ASSERT(!dfp[1].length);
ASSERT(!dfp[2].length);
}
}
/*
* The entry before us is free, merge with it.
*/
else if (prevdup) {
dfp = xfs_dir2_data_freefind(d, prevdup);
be16_add(&prevdup->length, len);
*XFS_DIR2_DATA_UNUSED_TAG_P(prevdup) =
cpu_to_be16((char *)prevdup - (char *)d);
xfs_dir2_data_log_unused(tp, bp, prevdup);
/*
* If the previous entry was in the table, the new entry
* is longer, so it will be in the table too. Remove
* the old one and add the new one.
*/
if (dfp) {
xfs_dir2_data_freeremove(d, dfp, needlogp);
(void)xfs_dir2_data_freeinsert(d, prevdup, needlogp);
}
/*
* Otherwise we need a scan if the new entry is big enough.
*/
else {
needscan = be16_to_cpu(prevdup->length) >
be16_to_cpu(d->hdr.bestfree[2].length);
}
}
/*
* The following entry is free, merge with it.
*/
else if (postdup) {
dfp = xfs_dir2_data_freefind(d, postdup);
newdup = (xfs_dir2_data_unused_t *)((char *)d + offset);
newdup->freetag = cpu_to_be16(XFS_DIR2_DATA_FREE_TAG);
newdup->length = cpu_to_be16(len + be16_to_cpu(postdup->length));
*XFS_DIR2_DATA_UNUSED_TAG_P(newdup) =
cpu_to_be16((char *)newdup - (char *)d);
xfs_dir2_data_log_unused(tp, bp, newdup);
/*
* If the following entry was in the table, the new entry
* is longer, so it will be in the table too. Remove
* the old one and add the new one.
*/
if (dfp) {
xfs_dir2_data_freeremove(d, dfp, needlogp);
(void)xfs_dir2_data_freeinsert(d, newdup, needlogp);
}
/*
* Otherwise we need a scan if the new entry is big enough.
*/
else {
needscan = be16_to_cpu(newdup->length) >
be16_to_cpu(d->hdr.bestfree[2].length);
}
}
/*
* Neither neighbor is free. Make a new entry.
*/
else {
newdup = (xfs_dir2_data_unused_t *)((char *)d + offset);
newdup->freetag = cpu_to_be16(XFS_DIR2_DATA_FREE_TAG);
newdup->length = cpu_to_be16(len);
*XFS_DIR2_DATA_UNUSED_TAG_P(newdup) =
cpu_to_be16((char *)newdup - (char *)d);
xfs_dir2_data_log_unused(tp, bp, newdup);
(void)xfs_dir2_data_freeinsert(d, newdup, needlogp);
}
*needscanp = needscan;
}
/*
* Take a byte range out of an existing unused space and make it un-free.
*/
void
xfs_dir2_data_use_free(
xfs_trans_t *tp, /* transaction pointer */
xfs_dabuf_t *bp, /* data block buffer */
xfs_dir2_data_unused_t *dup, /* unused entry */
xfs_dir2_data_aoff_t offset, /* starting offset to use */
xfs_dir2_data_aoff_t len, /* length to use */
int *needlogp, /* out: need to log header */
int *needscanp) /* out: need regen bestfree */
{
xfs_dir2_data_t *d; /* data block */
xfs_dir2_data_free_t *dfp; /* bestfree pointer */
int matchback; /* matches end of freespace */
int matchfront; /* matches start of freespace */
int needscan; /* need to regen bestfree */
xfs_dir2_data_unused_t *newdup; /* new unused entry */
xfs_dir2_data_unused_t *newdup2; /* another new unused entry */
int oldlen; /* old unused entry's length */
d = bp->data;
ASSERT(be32_to_cpu(d->hdr.magic) == XFS_DIR2_DATA_MAGIC ||
be32_to_cpu(d->hdr.magic) == XFS_DIR2_BLOCK_MAGIC);
ASSERT(be16_to_cpu(dup->freetag) == XFS_DIR2_DATA_FREE_TAG);
ASSERT(offset >= (char *)dup - (char *)d);
ASSERT(offset + len <= (char *)dup + be16_to_cpu(dup->length) - (char *)d);
ASSERT((char *)dup - (char *)d == be16_to_cpu(*XFS_DIR2_DATA_UNUSED_TAG_P(dup)));
/*
* Look up the entry in the bestfree table.
*/
dfp = xfs_dir2_data_freefind(d, dup);
oldlen = be16_to_cpu(dup->length);
ASSERT(dfp || oldlen <= be16_to_cpu(d->hdr.bestfree[2].length));
/*
* Check for alignment with front and back of the entry.
*/
matchfront = (char *)dup - (char *)d == offset;
matchback = (char *)dup + oldlen - (char *)d == offset + len;
ASSERT(*needscanp == 0);
needscan = 0;
/*
* If we matched it exactly we just need to get rid of it from
* the bestfree table.
*/
if (matchfront && matchback) {
if (dfp) {
needscan = (d->hdr.bestfree[2].offset != 0);
if (!needscan)
xfs_dir2_data_freeremove(d, dfp, needlogp);
}
}
/*
* We match the first part of the entry.
* Make a new entry with the remaining freespace.
*/
else if (matchfront) {
newdup = (xfs_dir2_data_unused_t *)((char *)d + offset + len);
newdup->freetag = cpu_to_be16(XFS_DIR2_DATA_FREE_TAG);
newdup->length = cpu_to_be16(oldlen - len);
*XFS_DIR2_DATA_UNUSED_TAG_P(newdup) =
cpu_to_be16((char *)newdup - (char *)d);
xfs_dir2_data_log_unused(tp, bp, newdup);
/*
* If it was in the table, remove it and add the new one.
*/
if (dfp) {
xfs_dir2_data_freeremove(d, dfp, needlogp);
dfp = xfs_dir2_data_freeinsert(d, newdup, needlogp);
ASSERT(dfp != NULL);
ASSERT(dfp->length == newdup->length);
ASSERT(be16_to_cpu(dfp->offset) == (char *)newdup - (char *)d);
/*
* If we got inserted at the last slot,
* that means we don't know if there was a better
* choice for the last slot, or not. Rescan.
*/
needscan = dfp == &d->hdr.bestfree[2];
}
}
/*
* We match the last part of the entry.
* Trim the allocated space off the tail of the entry.
*/
else if (matchback) {
newdup = dup;
newdup->length = cpu_to_be16(((char *)d + offset) - (char *)newdup);
*XFS_DIR2_DATA_UNUSED_TAG_P(newdup) =
cpu_to_be16((char *)newdup - (char *)d);
xfs_dir2_data_log_unused(tp, bp, newdup);
/*
* If it was in the table, remove it and add the new one.
*/
if (dfp) {
xfs_dir2_data_freeremove(d, dfp, needlogp);
dfp = xfs_dir2_data_freeinsert(d, newdup, needlogp);
ASSERT(dfp != NULL);
ASSERT(dfp->length == newdup->length);
ASSERT(be16_to_cpu(dfp->offset) == (char *)newdup - (char *)d);
/*
* If we got inserted at the last slot,
* that means we don't know if there was a better
* choice for the last slot, or not. Rescan.
*/
needscan = dfp == &d->hdr.bestfree[2];
}
}
/*
* Poking out the middle of an entry.
* Make two new entries.
*/
else {
newdup = dup;
newdup->length = cpu_to_be16(((char *)d + offset) - (char *)newdup);
*XFS_DIR2_DATA_UNUSED_TAG_P(newdup) =
cpu_to_be16((char *)newdup - (char *)d);
xfs_dir2_data_log_unused(tp, bp, newdup);
newdup2 = (xfs_dir2_data_unused_t *)((char *)d + offset + len);
newdup2->freetag = cpu_to_be16(XFS_DIR2_DATA_FREE_TAG);
newdup2->length = cpu_to_be16(oldlen - len - be16_to_cpu(newdup->length));
*XFS_DIR2_DATA_UNUSED_TAG_P(newdup2) =
cpu_to_be16((char *)newdup2 - (char *)d);
xfs_dir2_data_log_unused(tp, bp, newdup2);
/*
* If the old entry was in the table, we need to scan
* if the 3rd entry was valid, since these entries
* are smaller than the old one.
* If we don't need to scan that means there were 1 or 2
* entries in the table, and removing the old and adding
* the 2 new will work.
*/
if (dfp) {
needscan = (d->hdr.bestfree[2].length != 0);
if (!needscan) {
xfs_dir2_data_freeremove(d, dfp, needlogp);
(void)xfs_dir2_data_freeinsert(d, newdup,
needlogp);
(void)xfs_dir2_data_freeinsert(d, newdup2,
needlogp);
}
}
}
*needscanp = needscan;
}

View File

@ -1,188 +0,0 @@
/*
* Copyright (c) 2000,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
*/
#ifndef __XFS_DIR2_DATA_H__
#define __XFS_DIR2_DATA_H__
/*
* Directory format 2, data block structures.
*/
struct xfs_dabuf;
struct xfs_da_args;
struct xfs_inode;
struct xfs_trans;
/*
* Constants.
*/
#define XFS_DIR2_DATA_MAGIC 0x58443244 /* XD2D: for multiblock dirs */
#define XFS_DIR2_DATA_ALIGN_LOG 3 /* i.e., 8 bytes */
#define XFS_DIR2_DATA_ALIGN (1 << XFS_DIR2_DATA_ALIGN_LOG)
#define XFS_DIR2_DATA_FREE_TAG 0xffff
#define XFS_DIR2_DATA_FD_COUNT 3
/*
* Directory address space divided into sections,
* spaces separated by 32gb.
*/
#define XFS_DIR2_SPACE_SIZE (1ULL << (32 + XFS_DIR2_DATA_ALIGN_LOG))
#define XFS_DIR2_DATA_SPACE 0
#define XFS_DIR2_DATA_OFFSET (XFS_DIR2_DATA_SPACE * XFS_DIR2_SPACE_SIZE)
#define XFS_DIR2_DATA_FIRSTDB(mp) \
XFS_DIR2_BYTE_TO_DB(mp, XFS_DIR2_DATA_OFFSET)
/*
* Offsets of . and .. in data space (always block 0)
*/
#define XFS_DIR2_DATA_DOT_OFFSET \
((xfs_dir2_data_aoff_t)sizeof(xfs_dir2_data_hdr_t))
#define XFS_DIR2_DATA_DOTDOT_OFFSET \
(XFS_DIR2_DATA_DOT_OFFSET + XFS_DIR2_DATA_ENTSIZE(1))
#define XFS_DIR2_DATA_FIRST_OFFSET \
(XFS_DIR2_DATA_DOTDOT_OFFSET + XFS_DIR2_DATA_ENTSIZE(2))
/*
* Structures.
*/
/*
* Describe a free area in the data block.
* The freespace will be formatted as a xfs_dir2_data_unused_t.
*/
typedef struct xfs_dir2_data_free {
__be16 offset; /* start of freespace */
__be16 length; /* length of freespace */
} xfs_dir2_data_free_t;
/*
* Header for the data blocks.
* Always at the beginning of a directory-sized block.
* The code knows that XFS_DIR2_DATA_FD_COUNT is 3.
*/
typedef struct xfs_dir2_data_hdr {
__be32 magic; /* XFS_DIR2_DATA_MAGIC */
/* or XFS_DIR2_BLOCK_MAGIC */
xfs_dir2_data_free_t bestfree[XFS_DIR2_DATA_FD_COUNT];
} xfs_dir2_data_hdr_t;
/*
* Active entry in a data block. Aligned to 8 bytes.
* Tag appears as the last 2 bytes.
*/
typedef struct xfs_dir2_data_entry {
xfs_ino_t inumber; /* inode number */
__uint8_t namelen; /* name length */
__uint8_t name[1]; /* name bytes, no null */
/* variable offset */
xfs_dir2_data_off_t tag; /* starting offset of us */
} xfs_dir2_data_entry_t;
/*
* Unused entry in a data block. Aligned to 8 bytes.
* Tag appears as the last 2 bytes.
*/
typedef struct xfs_dir2_data_unused {
__be16 freetag; /* XFS_DIR2_DATA_FREE_TAG */
__be16 length; /* total free length */
/* variable offset */
__be16 tag; /* starting offset of us */
} xfs_dir2_data_unused_t;
typedef union {
xfs_dir2_data_entry_t entry;
xfs_dir2_data_unused_t unused;
} xfs_dir2_data_union_t;
/*
* Generic data block structure, for xfs_db.
*/
typedef struct xfs_dir2_data {
xfs_dir2_data_hdr_t hdr; /* magic XFS_DIR2_DATA_MAGIC */
xfs_dir2_data_union_t u[1];
} xfs_dir2_data_t;
/*
* Macros.
*/
/*
* Size of a data entry.
*/
#define XFS_DIR2_DATA_ENTSIZE(n) xfs_dir2_data_entsize(n)
static inline int xfs_dir2_data_entsize(int n)
{
return (int)roundup(offsetof(xfs_dir2_data_entry_t, name[0]) + (n) + \
(uint)sizeof(xfs_dir2_data_off_t), XFS_DIR2_DATA_ALIGN);
}
/*
* Pointer to an entry's tag word.
*/
#define XFS_DIR2_DATA_ENTRY_TAG_P(dep) xfs_dir2_data_entry_tag_p(dep)
static inline __be16 *
xfs_dir2_data_entry_tag_p(xfs_dir2_data_entry_t *dep)
{
return (__be16 *)((char *)dep +
XFS_DIR2_DATA_ENTSIZE(dep->namelen) - sizeof(__be16));
}
/*
* Pointer to a freespace's tag word.
*/
#define XFS_DIR2_DATA_UNUSED_TAG_P(dup) \
xfs_dir2_data_unused_tag_p(dup)
static inline __be16 *
xfs_dir2_data_unused_tag_p(xfs_dir2_data_unused_t *dup)
{
return (__be16 *)((char *)dup +
be16_to_cpu(dup->length) - sizeof(__be16));
}
/*
* Function declarations.
*/
#ifdef DEBUG
extern void xfs_dir2_data_check(struct xfs_inode *dp, struct xfs_dabuf *bp);
#else
#define xfs_dir2_data_check(dp,bp)
#endif
extern xfs_dir2_data_free_t *xfs_dir2_data_freefind(xfs_dir2_data_t *d,
xfs_dir2_data_unused_t *dup);
extern xfs_dir2_data_free_t *xfs_dir2_data_freeinsert(xfs_dir2_data_t *d,
xfs_dir2_data_unused_t *dup, int *loghead);
extern void xfs_dir2_data_freescan(struct xfs_mount *mp, xfs_dir2_data_t *d,
int *loghead, char *aendp);
extern int xfs_dir2_data_init(struct xfs_da_args *args, xfs_dir2_db_t blkno,
struct xfs_dabuf **bpp);
extern void xfs_dir2_data_log_entry(struct xfs_trans *tp, struct xfs_dabuf *bp,
xfs_dir2_data_entry_t *dep);
extern void xfs_dir2_data_log_header(struct xfs_trans *tp,
struct xfs_dabuf *bp);
extern void xfs_dir2_data_log_unused(struct xfs_trans *tp, struct xfs_dabuf *bp,
xfs_dir2_data_unused_t *dup);
extern void xfs_dir2_data_make_free(struct xfs_trans *tp, struct xfs_dabuf *bp,
xfs_dir2_data_aoff_t offset,
xfs_dir2_data_aoff_t len, int *needlogp,
int *needscanp);
extern void xfs_dir2_data_use_free(struct xfs_trans *tp, struct xfs_dabuf *bp,
xfs_dir2_data_unused_t *dup,
xfs_dir2_data_aoff_t offset,
xfs_dir2_data_aoff_t len, int *needlogp,
int *needscanp);
#endif /* __XFS_DIR2_DATA_H__ */

File diff suppressed because it is too large Load Diff

View File

@ -1,270 +0,0 @@
/*
* Copyright (c) 2000-2001,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
*/
#ifndef __XFS_DIR2_LEAF_H__
#define __XFS_DIR2_LEAF_H__
struct uio;
struct xfs_dabuf;
struct xfs_da_args;
struct xfs_inode;
struct xfs_mount;
struct xfs_trans;
/*
* Offset of the leaf/node space. First block in this space
* is the btree root.
*/
#define XFS_DIR2_LEAF_SPACE 1
#define XFS_DIR2_LEAF_OFFSET (XFS_DIR2_LEAF_SPACE * XFS_DIR2_SPACE_SIZE)
#define XFS_DIR2_LEAF_FIRSTDB(mp) \
XFS_DIR2_BYTE_TO_DB(mp, XFS_DIR2_LEAF_OFFSET)
/*
* Offset in data space of a data entry.
*/
typedef __uint32_t xfs_dir2_dataptr_t;
#define XFS_DIR2_MAX_DATAPTR ((xfs_dir2_dataptr_t)0xffffffff)
#define XFS_DIR2_NULL_DATAPTR ((xfs_dir2_dataptr_t)0)
/*
* Leaf block header.
*/
typedef struct xfs_dir2_leaf_hdr {
xfs_da_blkinfo_t info; /* header for da routines */
__be16 count; /* count of entries */
__be16 stale; /* count of stale entries */
} xfs_dir2_leaf_hdr_t;
/*
* Leaf block entry.
*/
typedef struct xfs_dir2_leaf_entry {
__be32 hashval; /* hash value of name */
__be32 address; /* address of data entry */
} xfs_dir2_leaf_entry_t;
/*
* Leaf block tail.
*/
typedef struct xfs_dir2_leaf_tail {
__be32 bestcount;
} xfs_dir2_leaf_tail_t;
/*
* Leaf block.
* bests and tail are at the end of the block for single-leaf only
* (magic = XFS_DIR2_LEAF1_MAGIC not XFS_DIR2_LEAFN_MAGIC).
*/
typedef struct xfs_dir2_leaf {
xfs_dir2_leaf_hdr_t hdr; /* leaf header */
xfs_dir2_leaf_entry_t ents[1]; /* entries */
/* ... */
xfs_dir2_data_off_t bests[1]; /* best free counts */
xfs_dir2_leaf_tail_t tail; /* leaf tail */
} xfs_dir2_leaf_t;
/*
* DB blocks here are logical directory block numbers, not filesystem blocks.
*/
#define XFS_DIR2_MAX_LEAF_ENTS(mp) xfs_dir2_max_leaf_ents(mp)
static inline int xfs_dir2_max_leaf_ents(struct xfs_mount *mp)
{
return (int)(((mp)->m_dirblksize - (uint)sizeof(xfs_dir2_leaf_hdr_t)) /
(uint)sizeof(xfs_dir2_leaf_entry_t));
}
/*
* Get address of the bestcount field in the single-leaf block.
*/
#define XFS_DIR2_LEAF_TAIL_P(mp,lp) xfs_dir2_leaf_tail_p(mp, lp)
static inline xfs_dir2_leaf_tail_t *
xfs_dir2_leaf_tail_p(struct xfs_mount *mp, xfs_dir2_leaf_t *lp)
{
return (xfs_dir2_leaf_tail_t *)
((char *)(lp) + (mp)->m_dirblksize -
(uint)sizeof(xfs_dir2_leaf_tail_t));
}
/*
* Get address of the bests array in the single-leaf block.
*/
#define XFS_DIR2_LEAF_BESTS_P(ltp) xfs_dir2_leaf_bests_p(ltp)
static inline __be16 *
xfs_dir2_leaf_bests_p(xfs_dir2_leaf_tail_t *ltp)
{
return (__be16 *)ltp - be32_to_cpu(ltp->bestcount);
}
/*
* Convert dataptr to byte in file space
*/
#define XFS_DIR2_DATAPTR_TO_BYTE(mp,dp) xfs_dir2_dataptr_to_byte(mp, dp)
static inline xfs_dir2_off_t
xfs_dir2_dataptr_to_byte(struct xfs_mount *mp, xfs_dir2_dataptr_t dp)
{
return (xfs_dir2_off_t)(dp) << XFS_DIR2_DATA_ALIGN_LOG;
}
/*
* Convert byte in file space to dataptr. It had better be aligned.
*/
#define XFS_DIR2_BYTE_TO_DATAPTR(mp,by) xfs_dir2_byte_to_dataptr(mp,by)
static inline xfs_dir2_dataptr_t
xfs_dir2_byte_to_dataptr(struct xfs_mount *mp, xfs_dir2_off_t by)
{
return (xfs_dir2_dataptr_t)((by) >> XFS_DIR2_DATA_ALIGN_LOG);
}
/*
* Convert byte in space to (DB) block
*/
#define XFS_DIR2_BYTE_TO_DB(mp,by) xfs_dir2_byte_to_db(mp, by)
static inline xfs_dir2_db_t
xfs_dir2_byte_to_db(struct xfs_mount *mp, xfs_dir2_off_t by)
{
return (xfs_dir2_db_t)((by) >> \
((mp)->m_sb.sb_blocklog + (mp)->m_sb.sb_dirblklog));
}
/*
* Convert dataptr to a block number
*/
#define XFS_DIR2_DATAPTR_TO_DB(mp,dp) xfs_dir2_dataptr_to_db(mp, dp)
static inline xfs_dir2_db_t
xfs_dir2_dataptr_to_db(struct xfs_mount *mp, xfs_dir2_dataptr_t dp)
{
return XFS_DIR2_BYTE_TO_DB(mp, XFS_DIR2_DATAPTR_TO_BYTE(mp, dp));
}
/*
* Convert byte in space to offset in a block
*/
#define XFS_DIR2_BYTE_TO_OFF(mp,by) xfs_dir2_byte_to_off(mp, by)
static inline xfs_dir2_data_aoff_t
xfs_dir2_byte_to_off(struct xfs_mount *mp, xfs_dir2_off_t by)
{
return (xfs_dir2_data_aoff_t)((by) & \
((1 << ((mp)->m_sb.sb_blocklog + (mp)->m_sb.sb_dirblklog)) - 1));
}
/*
* Convert dataptr to a byte offset in a block
*/
#define XFS_DIR2_DATAPTR_TO_OFF(mp,dp) xfs_dir2_dataptr_to_off(mp, dp)
static inline xfs_dir2_data_aoff_t
xfs_dir2_dataptr_to_off(struct xfs_mount *mp, xfs_dir2_dataptr_t dp)
{
return XFS_DIR2_BYTE_TO_OFF(mp, XFS_DIR2_DATAPTR_TO_BYTE(mp, dp));
}
/*
* Convert block and offset to byte in space
*/
#define XFS_DIR2_DB_OFF_TO_BYTE(mp,db,o) \
xfs_dir2_db_off_to_byte(mp, db, o)
static inline xfs_dir2_off_t
xfs_dir2_db_off_to_byte(struct xfs_mount *mp, xfs_dir2_db_t db,
xfs_dir2_data_aoff_t o)
{
return ((xfs_dir2_off_t)(db) << \
((mp)->m_sb.sb_blocklog + (mp)->m_sb.sb_dirblklog)) + (o);
}
/*
* Convert block (DB) to block (dablk)
*/
#define XFS_DIR2_DB_TO_DA(mp,db) xfs_dir2_db_to_da(mp, db)
static inline xfs_dablk_t
xfs_dir2_db_to_da(struct xfs_mount *mp, xfs_dir2_db_t db)
{
return (xfs_dablk_t)((db) << (mp)->m_sb.sb_dirblklog);
}
/*
* Convert byte in space to (DA) block
*/
#define XFS_DIR2_BYTE_TO_DA(mp,by) xfs_dir2_byte_to_da(mp, by)
static inline xfs_dablk_t
xfs_dir2_byte_to_da(struct xfs_mount *mp, xfs_dir2_off_t by)
{
return XFS_DIR2_DB_TO_DA(mp, XFS_DIR2_BYTE_TO_DB(mp, by));
}
/*
* Convert block and offset to dataptr
*/
#define XFS_DIR2_DB_OFF_TO_DATAPTR(mp,db,o) \
xfs_dir2_db_off_to_dataptr(mp, db, o)
static inline xfs_dir2_dataptr_t
xfs_dir2_db_off_to_dataptr(struct xfs_mount *mp, xfs_dir2_db_t db,
xfs_dir2_data_aoff_t o)
{
return XFS_DIR2_BYTE_TO_DATAPTR(mp, XFS_DIR2_DB_OFF_TO_BYTE(mp, db, o));
}
/*
* Convert block (dablk) to block (DB)
*/
#define XFS_DIR2_DA_TO_DB(mp,da) xfs_dir2_da_to_db(mp, da)
static inline xfs_dir2_db_t
xfs_dir2_da_to_db(struct xfs_mount *mp, xfs_dablk_t da)
{
return (xfs_dir2_db_t)((da) >> (mp)->m_sb.sb_dirblklog);
}
/*
* Convert block (dablk) to byte offset in space
*/
#define XFS_DIR2_DA_TO_BYTE(mp,da) xfs_dir2_da_to_byte(mp, da)
static inline xfs_dir2_off_t
xfs_dir2_da_to_byte(struct xfs_mount *mp, xfs_dablk_t da)
{
return XFS_DIR2_DB_OFF_TO_BYTE(mp, XFS_DIR2_DA_TO_DB(mp, da), 0);
}
/*
* Function declarations.
*/
extern int xfs_dir2_block_to_leaf(struct xfs_da_args *args,
struct xfs_dabuf *dbp);
extern int xfs_dir2_leaf_addname(struct xfs_da_args *args);
extern void xfs_dir2_leaf_compact(struct xfs_da_args *args,
struct xfs_dabuf *bp);
extern void xfs_dir2_leaf_compact_x1(struct xfs_dabuf *bp, int *indexp,
int *lowstalep, int *highstalep,
int *lowlogp, int *highlogp);
extern int xfs_dir2_leaf_getdents(struct xfs_trans *tp, struct xfs_inode *dp,
struct uio *uio, int *eofp,
struct xfs_dirent *dbp, xfs_dir2_put_t put);
extern int xfs_dir2_leaf_init(struct xfs_da_args *args, xfs_dir2_db_t bno,
struct xfs_dabuf **bpp, int magic);
extern void xfs_dir2_leaf_log_ents(struct xfs_trans *tp, struct xfs_dabuf *bp,
int first, int last);
extern void xfs_dir2_leaf_log_header(struct xfs_trans *tp,
struct xfs_dabuf *bp);
extern int xfs_dir2_leaf_lookup(struct xfs_da_args *args);
extern int xfs_dir2_leaf_removename(struct xfs_da_args *args);
extern int xfs_dir2_leaf_replace(struct xfs_da_args *args);
extern int xfs_dir2_leaf_search_hash(struct xfs_da_args *args,
struct xfs_dabuf *lbp);
extern int xfs_dir2_leaf_trim_data(struct xfs_da_args *args,
struct xfs_dabuf *lbp, xfs_dir2_db_t db);
extern int xfs_dir2_node_to_leaf(struct xfs_da_state *state);
#endif /* __XFS_DIR2_LEAF_H__ */

File diff suppressed because it is too large Load Diff

View File

@ -1,104 +0,0 @@
/*
* Copyright (c) 2000,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
*/
#ifndef __XFS_DIR2_NODE_H__
#define __XFS_DIR2_NODE_H__
/*
* Directory version 2, btree node format structures
*/
struct uio;
struct xfs_dabuf;
struct xfs_da_args;
struct xfs_da_state;
struct xfs_da_state_blk;
struct xfs_inode;
struct xfs_trans;
/*
* Offset of the freespace index.
*/
#define XFS_DIR2_FREE_SPACE 2
#define XFS_DIR2_FREE_OFFSET (XFS_DIR2_FREE_SPACE * XFS_DIR2_SPACE_SIZE)
#define XFS_DIR2_FREE_FIRSTDB(mp) \
XFS_DIR2_BYTE_TO_DB(mp, XFS_DIR2_FREE_OFFSET)
#define XFS_DIR2_FREE_MAGIC 0x58443246 /* XD2F */
typedef struct xfs_dir2_free_hdr {
__be32 magic; /* XFS_DIR2_FREE_MAGIC */
__be32 firstdb; /* db of first entry */
__be32 nvalid; /* count of valid entries */
__be32 nused; /* count of used entries */
} xfs_dir2_free_hdr_t;
typedef struct xfs_dir2_free {
xfs_dir2_free_hdr_t hdr; /* block header */
__be16 bests[1]; /* best free counts */
/* unused entries are -1 */
} xfs_dir2_free_t;
#define XFS_DIR2_MAX_FREE_BESTS(mp) \
(((mp)->m_dirblksize - (uint)sizeof(xfs_dir2_free_hdr_t)) / \
(uint)sizeof(xfs_dir2_data_off_t))
/*
* Convert data space db to the corresponding free db.
*/
#define XFS_DIR2_DB_TO_FDB(mp,db) xfs_dir2_db_to_fdb(mp, db)
static inline xfs_dir2_db_t
xfs_dir2_db_to_fdb(struct xfs_mount *mp, xfs_dir2_db_t db)
{
return (XFS_DIR2_FREE_FIRSTDB(mp) + (db) / XFS_DIR2_MAX_FREE_BESTS(mp));
}
/*
* Convert data space db to the corresponding index in a free db.
*/
#define XFS_DIR2_DB_TO_FDINDEX(mp,db) xfs_dir2_db_to_fdindex(mp, db)
static inline int
xfs_dir2_db_to_fdindex(struct xfs_mount *mp, xfs_dir2_db_t db)
{
return ((db) % XFS_DIR2_MAX_FREE_BESTS(mp));
}
extern void xfs_dir2_free_log_bests(struct xfs_trans *tp, struct xfs_dabuf *bp,
int first, int last);
extern int xfs_dir2_leaf_to_node(struct xfs_da_args *args,
struct xfs_dabuf *lbp);
extern xfs_dahash_t xfs_dir2_leafn_lasthash(struct xfs_dabuf *bp, int *count);
extern int xfs_dir2_leafn_lookup_int(struct xfs_dabuf *bp,
struct xfs_da_args *args, int *indexp,
struct xfs_da_state *state);
extern int xfs_dir2_leafn_order(struct xfs_dabuf *leaf1_bp,
struct xfs_dabuf *leaf2_bp);
extern int xfs_dir2_leafn_split(struct xfs_da_state *state,
struct xfs_da_state_blk *oldblk,
struct xfs_da_state_blk *newblk);
extern int xfs_dir2_leafn_toosmall(struct xfs_da_state *state, int *action);
extern void xfs_dir2_leafn_unbalance(struct xfs_da_state *state,
struct xfs_da_state_blk *drop_blk,
struct xfs_da_state_blk *save_blk);
extern int xfs_dir2_node_addname(struct xfs_da_args *args);
extern int xfs_dir2_node_lookup(struct xfs_da_args *args);
extern int xfs_dir2_node_removename(struct xfs_da_args *args);
extern int xfs_dir2_node_replace(struct xfs_da_args *args);
extern int xfs_dir2_node_trim_free(struct xfs_da_args *args, xfs_fileoff_t fo,
int *rvalp);
#endif /* __XFS_DIR2_NODE_H__ */

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