diff options
Diffstat (limited to 'sys/gnu/fs/xfs/FreeBSD')
55 files changed, 10782 insertions, 0 deletions
diff --git a/sys/gnu/fs/xfs/FreeBSD/support/atomic.h b/sys/gnu/fs/xfs/FreeBSD/support/atomic.h new file mode 100644 index 0000000..f8b6c91 --- /dev/null +++ b/sys/gnu/fs/xfs/FreeBSD/support/atomic.h @@ -0,0 +1,37 @@ +#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_sub_and_test(i, v) (atomic_fetchadd_int(&(v)->val, (-i) == 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__ */ diff --git a/sys/gnu/fs/xfs/FreeBSD/support/debug.c b/sys/gnu/fs/xfs/FreeBSD/support/debug.c new file mode 100644 index 0000000..72345f0 --- /dev/null +++ b/sys/gnu/fs/xfs/FreeBSD/support/debug.c @@ -0,0 +1,97 @@ +/* + * 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> + +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); +} + diff --git a/sys/gnu/fs/xfs/FreeBSD/support/debug.h b/sys/gnu/fs/xfs/FreeBSD/support/debug.h new file mode 100644 index 0000000..6c82c84 --- /dev/null +++ b/sys/gnu/fs/xfs/FreeBSD/support/debug.h @@ -0,0 +1,77 @@ +/* + * 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 *, ...); + +#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__)) +#define debug_stop_all_cpus(param) /* param is "cpumask_t *" */ + +#endif /* __XFS_SUPPORT_DEBUG_H__ */ diff --git a/sys/gnu/fs/xfs/FreeBSD/support/kdb.c b/sys/gnu/fs/xfs/FreeBSD/support/kdb.c new file mode 100644 index 0000000..2d3aac6 --- /dev/null +++ b/sys/gnu/fs/xfs/FreeBSD/support/kdb.c @@ -0,0 +1,63 @@ +#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> +#else +#error "Must have options for KDB, DDB in kernel config" +#endif + +#include <support/kdb.h> + +DB_SET(xfs, xfs_ddb_cmd, db_cmd_set, CS_MORE, NULL) +{ + db_error("No commands registered.\n"); +} + + +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 +db_putarea_size(unsigned long addr, void *res, size_t size) +{ + return 0; +} diff --git a/sys/gnu/fs/xfs/FreeBSD/support/kdb.h b/sys/gnu/fs/xfs/FreeBSD/support/kdb.h new file mode 100644 index 0000000..d85bd6d --- /dev/null +++ b/sys/gnu/fs/xfs/FreeBSD/support/kdb.h @@ -0,0 +1,44 @@ +#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__ */ diff --git a/sys/gnu/fs/xfs/FreeBSD/support/kmem.c b/sys/gnu/fs/xfs/FreeBSD/support/kmem.c new file mode 100644 index 0000000..c98e4bc --- /dev/null +++ b/sys/gnu/fs/xfs/FreeBSD/support/kmem.c @@ -0,0 +1,3 @@ +#include <support/kmem.h> + +MALLOC_DEFINE(M_XFS, "XFSALLOC", "XFS memory"); diff --git a/sys/gnu/fs/xfs/FreeBSD/support/kmem.h b/sys/gnu/fs/xfs/FreeBSD/support/kmem.h new file mode 100644 index 0000000..f457302 --- /dev/null +++ b/sys/gnu/fs/xfs/FreeBSD/support/kmem.h @@ -0,0 +1,65 @@ +#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) + +/* + * memory management routines + */ +#define KM_SLEEP M_WAITOK +#define KM_SLEEP_IO M_WAITOK +#define KM_NOFS M_WAITOK +#define KM_NOSLEEP M_NOWAIT +#define KM_CACHEALIGN 0 + +#define kmem_zone uma_zone + +typedef struct uma_zone kmem_zone_t; +typedef struct uma_zone xfs_zone_t; + +#define kmem_zone_init(len, name) \ + uma_zcreate(name, len, NULL, NULL, NULL, NULL, 0, 0) +#define kmem_zone_free(zone, ptr) \ + uma_zfree(zone, ptr) +#define kmem_cache_destroy(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__ */ diff --git a/sys/gnu/fs/xfs/FreeBSD/support/ktrace.c b/sys/gnu/fs/xfs/FreeBSD/support/ktrace.c new file mode 100644 index 0000000..462a665 --- /dev/null +++ b/sys/gnu/fs/xfs/FreeBSD/support/ktrace.c @@ -0,0 +1,348 @@ +/* + * 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> + +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_cache_destroy(ktrace_hdr_zone); + kmem_cache_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; +} diff --git a/sys/gnu/fs/xfs/FreeBSD/support/ktrace.h b/sys/gnu/fs/xfs/FreeBSD/support/ktrace.h new file mode 100644 index 0000000..b566ef8 --- /dev/null +++ b/sys/gnu/fs/xfs/FreeBSD/support/ktrace.h @@ -0,0 +1,101 @@ +/* + * 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__ */ diff --git a/sys/gnu/fs/xfs/FreeBSD/support/move.h b/sys/gnu/fs/xfs/FreeBSD/support/move.h new file mode 100644 index 0000000..856ec03 --- /dev/null +++ b/sys/gnu/fs/xfs/FreeBSD/support/move.h @@ -0,0 +1,48 @@ +/* + * 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__ */ diff --git a/sys/gnu/fs/xfs/FreeBSD/support/mrlock.c b/sys/gnu/fs/xfs/FreeBSD/support/mrlock.c new file mode 100644 index 0000000..9503039 --- /dev/null +++ b/sys/gnu/fs/xfs/FreeBSD/support/mrlock.c @@ -0,0 +1,49 @@ +#include <sys/param.h> +#include <support/mrlock.h> + +void +_sx_xfs_destroy(struct sx *sx) +{ + if (sx->sx_cnt == -1) + sx_xunlock(sx); + sx_destroy(sx); +} + +void +_sx_xfs_lock(struct sx *sx, int type, const char *file, int line) +{ + if (type == MR_ACCESS) + _sx_slock(sx, file, line); + else if (type == MR_UPDATE) + _sx_sunlock(sx, file, line); + else + panic("Invalid lock type passed"); +} + + +void +_sx_xfs_unlock(struct sx *sx, const char *file, int line) +{ + if (_sx_xfs_xowned(sx)) + _sx_xunlock(sx, file, line); + else if (_sx_xfs_sowned(sx)) + _sx_sunlock(sx, file, line); + else + panic("lock is not locked"); +} + +int +ismrlocked(mrlock_t *mrp, int type) +{ + if (type == MR_ACCESS) + return _sx_xfs_sowned(mrp); /* Read lock */ + else if (type == MR_UPDATE) + return _sx_xfs_xowned(mrp); /* Write lock */ + else if (type == (MR_UPDATE | MR_ACCESS)) + return _sx_xfs_sowned(mrp) || + _sx_xfs_xowned(mrp); /* Any type of lock held */ + return (mrp->sx_shrd_wcnt > 0 || mrp->sx_excl_wcnt > 0); +} + + + diff --git a/sys/gnu/fs/xfs/FreeBSD/support/mrlock.h b/sys/gnu/fs/xfs/FreeBSD/support/mrlock.h new file mode 100644 index 0000000..4e82d41 --- /dev/null +++ b/sys/gnu/fs/xfs/FreeBSD/support/mrlock.h @@ -0,0 +1,65 @@ +#ifndef __XFS_SUPPORT_MRLOCK_H__ +#define __XFS_SUPPORT_MRLOCK_H__ + +#include <sys/types.h> +#include <sys/systm.h> +#include <sys/lock.h> +#include <sys/mutex.h> +#include <sys/sx.h> + +#include <support/debug.h> + +/* + * Implement mrlocks on FreeBSD that work for XFS. + * Use FreeBSD sx lock and add necessary functions + * if additional functionality is requested + */ +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 + +/* + * mraccessf/mrupdatef take flags to be passed in while sleeping; + * only PLTWAIT is currently supported. + */ +#define mrinit(lock, name) sx_init(lock, name) +#define mrlock_init(lock, type, name, seq) sx_init(lock, name) +#define mrfree(lock) _sx_xfs_destroy(lock) +#define mraccessf(lock, f) sx_slock(lock) +#define mrupdatef(lock, f) sx_xlock(lock) +#define mraccunlock(lock) sx_sunlock(lock) +#define mrtryaccess(lock) sx_try_slock(lock) +#define mrtryupdate(lock) sx_try_xlock(lock) +#define mraccess(mrp) mraccessf(mrp, 0) +#define mrupdate(mrp) mrupdatef(mrp, 0) +#define mrislocked_access(lock) _sx_xfs_xowned(lock) +#define mrislocked_update(lock) _sx_xfs_sowned(lock) +#define mrtrypromote(lock) sx_try_upgrade(lock) +#define mrdemote(lock) sx_downgrade(lock) + +int ismrlocked(mrlock_t *, int); +void _sx_xfs_lock(struct sx *sx, int type, const char *file, int line); +void _sx_xfs_unlock(struct sx *sx, const char *file, int line); +void _sx_xfs_destroy(struct sx *sx); +#define _sx_xfs_xowned(lock) ((lock)->sx_cnt < 0) +#define _sx_xfs_sowned(lock) ((lock)->sx_cnt > 0) + +/* + * Functions, not implemented in FreeBSD + */ +#define mrunlock(lock) \ + _sx_xfs_unlock(lock, __FILE__, __LINE__) + +#define mrlock(lock, type, flags) \ + _sx_xfs_lock(lock, type, __FILE__, __LINE__) + + + +#endif /* __XFS_SUPPORT_MRLOCK_H__ */ diff --git a/sys/gnu/fs/xfs/FreeBSD/support/mutex.h b/sys/gnu/fs/xfs/FreeBSD/support/mutex.h new file mode 100644 index 0000000..d9b89b3 --- /dev/null +++ b/sys/gnu/fs/xfs/FreeBSD/support/mutex.h @@ -0,0 +1,29 @@ +#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__ */ diff --git a/sys/gnu/fs/xfs/FreeBSD/support/rwlock.h b/sys/gnu/fs/xfs/FreeBSD/support/rwlock.h new file mode 100644 index 0000000..05f489e --- /dev/null +++ b/sys/gnu/fs/xfs/FreeBSD/support/rwlock.h @@ -0,0 +1,22 @@ +#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_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__ */ diff --git a/sys/gnu/fs/xfs/FreeBSD/support/rwsem.h b/sys/gnu/fs/xfs/FreeBSD/support/rwsem.h new file mode 100644 index 0000000..bb97232 --- /dev/null +++ b/sys/gnu/fs/xfs/FreeBSD/support/rwsem.h @@ -0,0 +1,21 @@ +#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__ */ diff --git a/sys/gnu/fs/xfs/FreeBSD/support/sema.h b/sys/gnu/fs/xfs/FreeBSD/support/sema.h new file mode 100644 index 0000000..db7795b --- /dev/null +++ b/sys/gnu/fs/xfs/FreeBSD/support/sema.h @@ -0,0 +1,53 @@ +/*- + * 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__ */ diff --git a/sys/gnu/fs/xfs/FreeBSD/support/spin.h b/sys/gnu/fs/xfs/FreeBSD/support/spin.h new file mode 100644 index 0000000..2b09be4 --- /dev/null +++ b/sys/gnu/fs/xfs/FreeBSD/support/spin.h @@ -0,0 +1,42 @@ +#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) {} \ + } while (0) + +#endif /* __XFS_SUPPORT_SPIN_H__ */ diff --git a/sys/gnu/fs/xfs/FreeBSD/support/support.h b/sys/gnu/fs/xfs/FreeBSD/support/support.h new file mode 100644 index 0000000..d7804fa --- /dev/null +++ b/sys/gnu/fs/xfs/FreeBSD/support/support.h @@ -0,0 +1,49 @@ +/* + * 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__ */ diff --git a/sys/gnu/fs/xfs/FreeBSD/support/sv.h b/sys/gnu/fs/xfs/FreeBSD/support/sv.h new file mode 100644 index 0000000..fa37129 --- /dev/null +++ b/sys/gnu/fs/xfs/FreeBSD/support/sv.h @@ -0,0 +1,34 @@ +#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) +#define sv_wait(sv, pri, lock, spl) \ + cv_wait_unlock(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__ */ diff --git a/sys/gnu/fs/xfs/FreeBSD/support/time.h b/sys/gnu/fs/xfs/FreeBSD/support/time.h new file mode 100644 index 0000000..9b3a974 --- /dev/null +++ b/sys/gnu/fs/xfs/FreeBSD/support/time.h @@ -0,0 +1,37 @@ +/* + * 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__ */ diff --git a/sys/gnu/fs/xfs/FreeBSD/support/uuid.c b/sys/gnu/fs/xfs/FreeBSD/support/uuid.c new file mode 100644 index 0000000..55344c0 --- /dev/null +++ b/sys/gnu/fs/xfs/FreeBSD/support/uuid.c @@ -0,0 +1,165 @@ +/* + * 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); +} diff --git a/sys/gnu/fs/xfs/FreeBSD/support/uuid.h b/sys/gnu/fs/xfs/FreeBSD/support/uuid.h new file mode 100644 index 0000000..d8f389a --- /dev/null +++ b/sys/gnu/fs/xfs/FreeBSD/support/uuid.h @@ -0,0 +1,45 @@ +/* + * 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__ */ diff --git a/sys/gnu/fs/xfs/FreeBSD/xfs_buf.c b/sys/gnu/fs/xfs/FreeBSD/xfs_buf.c new file mode 100644 index 0000000..ac300db --- /dev/null +++ b/sys/gnu/fs/xfs/FreeBSD/xfs_buf.c @@ -0,0 +1,188 @@ +/* + * + * + */ +#include "xfs.h" +#include "xfs_macros.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> + +xfs_buf_t * +xfs_buf_read_flags(xfs_buftarg_t *target, xfs_daddr_t blkno, size_t len, int flags) +{ + struct buf *bp; + struct g_consumer *cp; + + KASSERT((target != NULL), ("got NULL buftarg_t")); + + cp = target->specvp->v_bufobj.bo_private; + if (cp == NULL) { + bp = NULL; + goto done; + } + + /* This restriction is in GEOM's g_io_request() */ + if ((BBTOB(len) % cp->provider->sectorsize) != 0) { + printf("Read request %ld does not align with sector size: %d\n", + (long)BBTOB(len), cp->provider->sectorsize); + bp = NULL; + goto done; + } + + if (bread(target->specvp, blkno, BBTOB(len), NOCRED, &bp)) { + printf("bread failed specvp %p blkno %qd BBTOB(len) %ld\n", + target->specvp, blkno, (long)BBTOB(len)); + bp = NULL; + goto done; + } + if (flags & B_MANAGED) + bp->b_flags |= B_MANAGED; + xfs_buf_set_target(bp, target); + +done: + 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); + if (bp != NULL) { + bp->b_bufsize = size; + bp->b_bcount = size; + + KASSERT(BUF_REFCNT(bp) == 1, + ("xfs_buf_get_empty: bp %p not locked",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); + if (bp != NULL) { + KASSERT(BUF_REFCNT(bp) == 1, + ("xfs_buf_get_empty: bp %p not locked",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_baread(xfs_buftarg_t *targp, xfs_daddr_t ioff, size_t isize) +{ + daddr_t rablkno; + int rabsize; + + rablkno = ioff; + rabsize = BBTOB(isize); + breada(targp->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 (BUF_REFCNT(bp) > 1) + BUF_UNLOCK(bp); + else + brelse(bp); + } + return (error); + } + error = bwrite(bp); + return (error); +} + +void +xfs_bpin(xfs_buf_t *bp) +{ + printf("xfs_bpin(%p)\n", bp); + bpin(bp); +} + +void +xfs_bunpin(xfs_buf_t *bp) +{ + printf("xfs_bunpin(%p)\n", bp); + bunpin(bp); +} + +int +xfs_ispin(xfs_buf_t *bp) +{ + printf("xfs_ispin(%p)\n", bp); + return bp->b_pin_count; +} + +void +xfs_bwait_unpin(xfs_buf_t *bp) +{ + printf("xfs_bwait_unpin(%p)\n", bp); + bunpin_wait(bp); +} diff --git a/sys/gnu/fs/xfs/FreeBSD/xfs_buf.h b/sys/gnu/fs/xfs/FreeBSD/xfs_buf.h new file mode 100644 index 0000000..54a7fc6 --- /dev/null +++ b/sys/gnu/fs/xfs/FreeBSD/xfs_buf.h @@ -0,0 +1,304 @@ +/* + * 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> + +/* XXX: move this into buf.h */ +#ifndef B_MANAGED +#define B_MANAGED B_08000000 +#endif + +struct xfs_buf; +struct xfs_mount; +struct vnode; + +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 { + struct cdev *dev; + struct vnode *specvp; +} xfs_buftarg_t; + +typedef struct buf xfs_buf_t; +#define xfs_buf buf + +/* 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 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 + + /* 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) +#define XFS_BUF_UNSTALE(x) ((x)->b_flags &= ~XFS_B_STALE) +#define XFS_BUF_ISSTALE(x) ((x)->b_flags & XFS_B_STALE) +#define XFS_BUF_SUPER_STALE(x) {(x)->b_flags |= XFS_B_STALE;\ + (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_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_ISHOLD(x) BUF_REFCNT(x) + +#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_REFCNT(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_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) + +#define xfs_bdwrite(mp, bp) bdwrite(bp) +/* + { ((bp)->b_vp == NULL) ? (bp)->b_bdstrat = xfs_bdstrat_cb: 0; \ + (bp)->b_fsprivate3 = (mp); bdwrite(bp);} +*/ +#define xfs_bawrite(mp, bp) bawrite(bp) +/* + { ((bp)->b_vp == NULL) ? (bp)->b_bdstrat = xfs_bdstrat_cb: 0; \ + (bp)->b_fsprivate3 = (mp); bawrite(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(pb, off, len, data, rw) \ + panic("%s:%d: xfs_biomove NI", __FILE__, __LINE__) + +#define xfs_biozero(pb, off, len) \ + panic("%s:%d: xfs_biozero NI", __FILE__, __LINE__) + +/* already a function xfs_bwrite... fix this */ +#define XFS_bdwrite(bp) bdwrite(bp) +#define xfs_iowait(bp) bufwait(bp) + +#define xfs_binval(buftarg) printf("binval(buftarg.dev) NI\n") +#define XFS_bflush(buftarg) printf("bflush(buftarg.dev) NI\n") + +#define XFS_bdstrat(bp) printf("XFS_bdstrat NI\n") + +#define xfs_incore_relse(buftarg,delwri_only,wait) \ + printf("incore_relse(buftarg.dev,delwri_only,wait) NI\n") + +#define xfs_incore_match(buftarg,blkno,len,field,value) \ + printf("incore_match(buftarg.dev,blkno,len,field,value) NI \n") + +void xfs_baread(xfs_buftarg_t *targp, xfs_daddr_t ioff, size_t isize); + +extern void pdflush(struct vnode *, uint64_t); +#define XFS_pdflush(vnode,flags) \ + pdflush(vnode,flags) + +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 *); +int xfs_buf_iorequest(struct xfs_buf *bp); + +void XFS_freerbuf(xfs_buf_t *bp); +void XFS_nfreerbuf(xfs_buf_t *bp); + +void xfs_bpin(xfs_buf_t *bp); +void xfs_bunpin(xfs_buf_t *bp); +int xfs_ispin(xfs_buf_t *bp); +void xfs_bwait_unpin(xfs_buf_t *bp); + +#endif diff --git a/sys/gnu/fs/xfs/FreeBSD/xfs_compat.h b/sys/gnu/fs/xfs/FreeBSD/xfs_compat.h new file mode 100644 index 0000000..d89e38b --- /dev/null +++ b/sys/gnu/fs/xfs/FreeBSD/xfs_compat.h @@ -0,0 +1,165 @@ +#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; + +/* + * 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 + +/* + * 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 + +#ifndef memmove +#define memmove(dst, src, len) bcopy((src), (dst), (len)) +#endif + +#ifndef barrier +#define barrier() __asm__ __volatile__("": : :"memory") +#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)) + + +/* + * Cedentials manipulation. + */ +#define current_fsuid(credp) (credp)->cr_uid +#define current_fsgid(credp) (credp)->cr_groups[0] + +#endif /* __XFS_COMPAT_H__ */ diff --git a/sys/gnu/fs/xfs/FreeBSD/xfs_config.h b/sys/gnu/fs/xfs/FreeBSD/xfs_config.h new file mode 100644 index 0000000..a115f54 --- /dev/null +++ b/sys/gnu/fs/xfs/FreeBSD/xfs_config.h @@ -0,0 +1,38 @@ +#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__ */ diff --git a/sys/gnu/fs/xfs/FreeBSD/xfs_cred.h b/sys/gnu/fs/xfs/FreeBSD/xfs_cred.h new file mode 100644 index 0000000..bc59977 --- /dev/null +++ b/sys/gnu/fs/xfs/FreeBSD/xfs_cred.h @@ -0,0 +1,46 @@ +/* + * 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__ */ diff --git a/sys/gnu/fs/xfs/FreeBSD/xfs_dmistubs.c b/sys/gnu/fs/xfs/FreeBSD/xfs_dmistubs.c new file mode 100644 index 0000000..746747e --- /dev/null +++ b/sys/gnu/fs/xfs/FreeBSD/xfs_dmistubs.c @@ -0,0 +1,143 @@ +/* + * 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_macros.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) +{ + return (0); +} + +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(); +} diff --git a/sys/gnu/fs/xfs/FreeBSD/xfs_freebsd.h b/sys/gnu/fs/xfs/FreeBSD/xfs_freebsd.h new file mode 100644 index 0000000..d7a30d6 --- /dev/null +++ b/sys/gnu/fs/xfs/FreeBSD/xfs_freebsd.h @@ -0,0 +1,356 @@ +/* + * 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> +#include <xfs_log.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 xfs_refcache_size xfs_params.refcache_size.val +#define xfs_refcache_purge_count xfs_params.refcache_purge.val +#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_interval xfs_params.sync_interval.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_flush_interval xfs_params.flush_interval.val +#define xfs_age_buffer xfs_params.age_buffer.val +#define xfs_io_bypass xfs_params.io_bypass.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 */ + +/* + * Size of block device i/o is parameterized here. + * Currently the system supports page-sized i/o. + */ +#define BLKDEV_IOSHIFT BPCSHIFT +#ifndef BLKDEV_IOSIZE +#define BLKDEV_IOSIZE (1<<BLKDEV_IOSHIFT) +#else +# if NBPC != BLKDEV_IOSIZE +# error Wrong BLKDEV_IOSIZE +# endif +#endif +/* 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() barrier() +#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)) + +/* + * 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(); +} + + +/* 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); +} + +static inline unsigned long ffz(unsigned long val) +{ + val = ffsl(~val); + return val; +} + +#endif /* __XFS_FREEBSD__ */ diff --git a/sys/gnu/fs/xfs/FreeBSD/xfs_frw.c b/sys/gnu/fs/xfs/FreeBSD/xfs_frw.c new file mode 100644 index 0000000..ac9f2dc --- /dev/null +++ b/sys/gnu/fs/xfs/FreeBSD/xfs_frw.c @@ -0,0 +1,1040 @@ +/* + * 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/ + */ +/* + * fs/xfs/linux/xfs_lrw.c (Linux Read Write stuff) + * + */ + +#include "xfs.h" + +#include "xfs_fs.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_alloc.h" +#include "xfs_dmapi.h" +#include "xfs_quota.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_ialloc.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_bmap.h" +#include "xfs_bit.h" +#include "xfs_rtalloc.h" +#include "xfs_error.h" +#include "xfs_itable.h" +#include "xfs_rw.h" +#include "xfs_refcache.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 */ + loff_t pos, /* offset in file */ + size_t count, /* size of data to zero */ + loff_t end_size) /* max file size to set */ +{ +#if XXXKAN + unsigned bytes; + struct page *page; + struct address_space *mapping; + char *kaddr; + int status; + + 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); + + return (-status); +#endif /* XXXKAN */ + return (0); +} + +/* + * xfs_inval_cached_pages + * + * This routine is responsible for keeping direct I/O and buffered I/O + * somewhat coherent. From here we make sure that we're at least + * temporarily holding the inode I/O lock exclusively and then call + * the page cache to flush and invalidate any cached pages. If there + * are no cached pages this routine will be very quick. + */ +void +xfs_inval_cached_pages( + xfs_vnode_t *vp, + xfs_iocore_t *io, + xfs_off_t offset, + int write, + int relock) +{ + xfs_mount_t *mp; + + if (!VN_CACHED(vp)) { + return; + } + + mp = io->io_mount; + + /* + * We need to get the I/O lock exclusively in order + * to safely invalidate pages and mappings. + */ + if (relock) { + XFS_IUNLOCK(mp, io, XFS_IOLOCK_SHARED); + XFS_ILOCK(mp, io, XFS_IOLOCK_EXCL); + } + + /* Writing beyond EOF creates a hole that must be zeroed */ + if (write && (offset > XFS_SIZE(mp, io))) { + xfs_fsize_t isize; + + XFS_ILOCK(mp, io, XFS_ILOCK_EXCL|XFS_EXTSIZE_RD); + isize = XFS_SIZE(mp, io); + if (offset > isize) { + xfs_zero_eof(vp, io, offset, isize, offset); + } + XFS_IUNLOCK(mp, io, XFS_ILOCK_EXCL|XFS_EXTSIZE_RD); + } + + xfs_inval_cached_trace(io, offset, -1, ctooff(offtoct(offset)), -1); + XVOP_FLUSHINVAL_PAGES(vp, ctooff(offtoct(offset)), -1, FI_REMAPF_LOCKED); + if (relock) { + XFS_ILOCK_DEMOTE(mp, io, XFS_IOLOCK_EXCL); + } +} + +int +xfs_read_file(xfs_mount_t *mp, xfs_inode_t *ip, struct uio *uio, int ioflag); + +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; + } + + if (!(ioflags & IO_ISLOCKED)) + xfs_ilock(ip, XFS_IOLOCK_SHARED); +#if XXXKAN + 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) { + if (!(ioflags & IO_ISLOCKED)) + xfs_iunlock(ip, XFS_IOLOCK_SHARED); + return (error); + } + } + + if (unlikely(ioflags & IO_ISDIRECT)) { + xfs_rw_enter_trace(XFS_DIORD_ENTER, &ip->i_iocore, + buf, size, *offset, ioflags); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,22) + xfs_off_t pos = uio->uio_offset; + + ret = generic_file_direct_IO(READ, file, buf, size, pos); + if (ret > 0) + uio->uio_offset = pos + ret; + + UPDATE_ATIME(file->f_dentry->d_inode); +#else + ret = generic_file_read(file, buf, size, offset); +#endif + } else { + xfs_rw_enter_trace(XFS_READ_ENTER, &ip->i_iocore, + buf, size, *offset, ioflags); + ret = generic_file_read(file, buf, size, offset); + } +#else /* XXXKAN */ + ret = xfs_read_file(mp, ip, uio, ioflags); +#endif /* XXXKAN */ + + if (!(ioflags & IO_ISLOCKED)) + 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_off_t offset, + 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 isize_fsb_offset; + int error = 0; + xfs_bmbt_irec_t imap; + loff_t loff; + size_t lsize; + + ASSERT(ismrlocked(io->io_lock, MR_UPDATE) != 0); + ASSERT(offset > isize); + + mp = io->io_mount; + + isize_fsb_offset = XFS_B_FSB_OFFSET(mp, isize); + if (isize_fsb_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); + 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); + lsize = XFS_FSB_TO_B(mp, 1); + + zero_offset = isize_fsb_offset; + zero_len = mp->m_sb.sb_blocksize - isize_fsb_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 prev_zero_fsb; + xfs_fileoff_t zero_count_fsb; + xfs_fileoff_t last_fsb; + xfs_extlen_t buf_len_fsb; + xfs_extlen_t prev_zero_count; + xfs_mount_t *mp; + int nimaps; + int error = 0; + xfs_bmbt_irec_t imap; + loff_t loff; + size_t lsize; + + ASSERT(ismrlocked(io->io_lock, MR_UPDATE)); + ASSERT(ismrlocked(io->io_iolock, MR_UPDATE)); + + 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, offset, 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); + prev_zero_fsb = NULLFILEOFF; + prev_zero_count = 0; + 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); + 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. + */ + prev_zero_fsb = NULLFILEOFF; + prev_zero_count = 0; + 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); + + loff = XFS_FSB_TO_B(mp, start_zero_fsb); + lsize = XFS_FSB_TO_B(mp, buf_len_fsb); + + error = xfs_iozero(vp, loff, lsize, end_size); + + if (error) { + goto out_lock; + } + + prev_zero_fsb = start_zero_fsb; + prev_zero_count = buf_len_fsb; + 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 *uiop, + int ioflags, + cred_t *credp) +{ +#if XXXKAN + xfs_inode_t *xip; + xfs_mount_t *mp; + ssize_t ret; + int error = 0; + xfs_fsize_t isize, new_size; + xfs_fsize_t n, limit; + xfs_iocore_t *io; + xfs_vnode_t *vp; + int iolock; + int eventsent = 0; + vrwlock_t locktype; + + XFS_STATS_INC(xs_write_calls); + + vp = BHV_TO_VNODE(bdp); + xip = XFS_BHVTOI(bdp); + + if (size == 0) + return 0; + + io = &xip->i_iocore; + mp = io->io_mount; + + xfs_check_frozen(mp, bdp, XFS_FREEZE_WRITE); + + if (XFS_FORCED_SHUTDOWN(xip->i_mount)) { + return EIO; + } + + if (unlikely(ioflags & 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; + } + + if (ioflags & IO_ISLOCKED) + iolock = 0; + + xfs_ilock(xip, XFS_ILOCK_EXCL|iolock); + + isize = xip->i_d.di_size; + limit = XFS_MAXIOFFSET(mp); + + if (file->f_flags & 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; + } + + 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; + } + } + + /* + * 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 (!(ioflags & 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 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 (error) { + xfs_iunlock(xip, iolock); + return -error; + } + } + + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,22) + if ((ssize_t) size < 0) { + ret = EINVAL; + goto error; + } + + if (!access_ok(VERIFY_READ, buf, size)) { + ret = EINVAL; + goto error; + } +#else +#define do_generic_direct_write(file, buf, size, offset) \ + generic_file_write_nolock(file, buf, size, offset) +#define do_generic_file_write(file, buf, size, offset) \ + generic_file_write_nolock(file, buf, size, offset) +#endif + +retry: + if (unlikely(ioflags & IO_ISDIRECT)) { + loff_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); + if (ret > 0) + *offset += ret; + } else { + xfs_rw_enter_trace(XFS_WRITE_ENTER, io, buf, size, *offset, ioflags); + ret = do_generic_file_write(file, buf, size, offset); + } + + if (unlikely(ioflags & IO_INVIS)) { + /* generic_file_write updates the mtime/ctime but we need + * to undo that because this I/O was supposed to be + * invisible. + */ + struct inode *inode = LINVFS_GET_IP(vp); + inode->i_mtime = xip->i_d.di_mtime.t_sec; + inode->i_ctime = xip->i_d.di_ctime.t_sec; + } else { + xfs_ichgtime(xip, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG); + } + + if ((ret == -ENOSPC) && + DM_EVENT_ENABLED(vp->v_vfsp, xip, DM_EVENT_NOSPACE) && + !(ioflags & IO_INVIS)) { + + xfs_rwunlock(bdp, locktype); + error = XFS_SEND_NAMESP(xip->i_mount, DM_EVENT_NOSPACE, vp, + DM_RIGHT_NULL, vp, DM_RIGHT_NULL, NULL, NULL, + 0, 0, 0); /* Delay flag intentionally unused */ + if (error) + return -error; + xfs_rwlock(bdp, locktype); + *offset = xip->i_d.di_size; + goto retry; + } + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,22) +error: +#endif + 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) { + struct inode *inode = LINVFS_GET_IP(vp); + + xip->i_d.di_size = *offset; + i_size_write(inode, *offset); + xip->i_update_core = 1; + xip->i_update_size = 1; + mark_inode_dirty_sync(inode); + } + xfs_iunlock(xip, XFS_ILOCK_EXCL); + } + + /* Handle various SYNC-type writes */ + if ((file->f_flags & O_SYNC) || IS_SYNC(file->f_dentry->d_inode)) { + + /* + * 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)) { + /* + * 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. + */ + + xfs_inode_log_item_t *iip; + xfs_lsn_t lsn; + + iip = xip->i_itemp; + if (iip && iip->ili_last_lsn) { + lsn = iip->ili_last_lsn; + xfs_log_force(mp, 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, (xfs_lsn_t)0); + xfs_iunlock(xip, XFS_ILOCK_EXCL); + } + } + } /* (ioflags & O_SYNC) */ + + /* + * If we are coming from an nfsd thread then insert into the + * reference cache. + */ + + if (!strcmp(current->comm, "nfsd")) + xfs_refcache_insert(xip); + + /* Drop lock this way - the old refcache release is in here */ + if (iolock) + xfs_rwunlock(bdp, locktype); + + return(ret); +#endif /* XXXKAN */ + return (0); +} + +/* + * 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)) { + /* Grio redirection would go here + * if (XFS_BUF_IS_GRIO(bp)) { + */ + + return 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; +} diff --git a/sys/gnu/fs/xfs/FreeBSD/xfs_frw.h b/sys/gnu/fs/xfs/FreeBSD/xfs_frw.h new file mode 100644 index 0000000..c08abce --- /dev/null +++ b/sys/gnu/fs/xfs/FreeBSD/xfs_frw.h @@ -0,0 +1,109 @@ +/* + * 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 *); + +#define XFS_FSB_TO_DB_IO(io,fsb) \ + (((io)->io_flags & XFS_IOCORE_RT) ? \ + XFS_FSB_TO_BB((io)->io_mount, (fsb)) : \ + XFS_FSB_TO_DADDR((io)->io_mount, (fsb))) + +#endif /* __XFS_FRW_H__ */ diff --git a/sys/gnu/fs/xfs/FreeBSD/xfs_fs_subr.c b/sys/gnu/fs/xfs/FreeBSD/xfs_fs_subr.c new file mode 100644 index 0000000..5a581ab --- /dev/null +++ b/sys/gnu/fs/xfs/FreeBSD/xfs_fs_subr.c @@ -0,0 +1,131 @@ +/* + * 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) +{ +#if 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) +{ +#if 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) +{ +#if 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; +} diff --git a/sys/gnu/fs/xfs/FreeBSD/xfs_fs_subr.h b/sys/gnu/fs/xfs/FreeBSD/xfs_fs_subr.h new file mode 100644 index 0000000..198b8dd --- /dev/null +++ b/sys/gnu/fs/xfs/FreeBSD/xfs_fs_subr.h @@ -0,0 +1,49 @@ +/* + * 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__ */ diff --git a/sys/gnu/fs/xfs/FreeBSD/xfs_globals.c b/sys/gnu/fs/xfs/FreeBSD/xfs_globals.c new file mode 100644 index 0000000..85f34fc --- /dev/null +++ b/sys/gnu/fs/xfs/FreeBSD/xfs_globals.c @@ -0,0 +1,71 @@ +/* + * 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_macros.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 }, + .sync_interval = { 1, 30, 60 }, + .stats_clear = { 0, 0, 1 }, + .inherit_sync = { 0, 1, 1 }, + .inherit_nodump = { 0, 1, 1 }, + .inherit_noatim = { 0, 1, 1 }, +}; + +/* + * Global system credential structure. + */ +cred_t sys_cred_val, *sys_cred = &sys_cred_val; diff --git a/sys/gnu/fs/xfs/FreeBSD/xfs_iget.c b/sys/gnu/fs/xfs/FreeBSD/xfs_iget.c new file mode 100644 index 0000000..45485bb --- /dev/null +++ b/sys/gnu/fs/xfs/FreeBSD/xfs_iget.c @@ -0,0 +1,973 @@ +/* + * 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_macros.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_alloc_btree.h" +#include "xfs_bmap_btree.h" +#include "xfs_ialloc_btree.h" +#include "xfs_btree.h" +#include "xfs_ialloc.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_quota.h" +#include "xfs_utils.h" +#include "xfs_vnode.h" + + +static int xfs_vn_allocate(xfs_mount_t *, xfs_inode_t *, struct xfs_vnode **); + +/* + * Initialize the inode hash table for the newly mounted file system. + * + * mp -- this is the mount point structure for the file system being + * initialized + */ +void +xfs_ihash_init(xfs_mount_t *mp) +{ + int i; + + mp->m_ihsize = XFS_BUCKETS(mp); + mp->m_ihash = (xfs_ihash_t *)kmem_zalloc(mp->m_ihsize + * sizeof(xfs_ihash_t), KM_SLEEP); + ASSERT(mp->m_ihash != NULL); + for (i = 0; i < mp->m_ihsize; i++) { + rwlock_init(&(mp->m_ihash[i].ih_lock)); + } +} + +/* + * Free up structures allocated by xfs_ihash_init, at unmount time. + */ +void +xfs_ihash_free(xfs_mount_t *mp) +{ + int i; + + for (i = 0; i < mp->m_ihsize; i++) + rwlock_destroy(&mp->m_ihash[i].ih_lock); + kmem_free(mp->m_ihash, mp->m_ihsize*sizeof(xfs_ihash_t)); + mp->m_ihash = NULL; +} + +/* + * Initialize the inode cluster hash table for the newly mounted file system. + * + * mp -- this is the mount point structure for the file system being + * initialized + */ +void +xfs_chash_init(xfs_mount_t *mp) +{ + int i; + + /* + * m_chash size is based on m_ihash + * with a minimum of 37 entries + */ + mp->m_chsize = (XFS_BUCKETS(mp)) / + (XFS_INODE_CLUSTER_SIZE(mp) >> mp->m_sb.sb_inodelog); + if (mp->m_chsize < 37) { + mp->m_chsize = 37; + } + mp->m_chash = (xfs_chash_t *)kmem_zalloc(mp->m_chsize + * sizeof(xfs_chash_t), + KM_SLEEP); + ASSERT(mp->m_chash != NULL); + + for (i = 0; i < mp->m_chsize; i++) { + spinlock_init(&mp->m_chash[i].ch_lock,"xfshash"); + } +} + +/* + * Free up structures allocated by xfs_chash_init, at unmount time. + */ +void +xfs_chash_free(xfs_mount_t *mp) +{ + int i; + + for (i = 0; i < mp->m_chsize; i++) { + spinlock_destroy(&mp->m_chash[i].ch_lock); + } + + kmem_free(mp->m_chash, mp->m_chsize*sizeof(xfs_chash_t)); + mp->m_chash = NULL; +} + +/* + * 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 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; +} + +/* + * Do the setup for the various locks within the incore inode. + */ +void +xfs_inode_lock_init( + xfs_inode_t *ip, + xfs_vnode_t *vp) +{ + mrlock_init(&ip->i_lock, MRLOCK_ALLOW_EQUAL_PRI|MRLOCK_BARRIER, + "xfsino", (long)vp->v_number); + mrlock_init(&ip->i_iolock, MRLOCK_BARRIER, "xfsio", vp->v_number); +#if XXXKAN + init_waitqueue_head(&ip->i_ipin_wait); +#endif + atomic_set(&ip->i_pincount, 0); + init_sema(&ip->i_flock, 1, "xfsfino", vp->v_number); +} + +/* + * Look for the inode corresponding to the given ino in the hash table. + * If it is there and its i_transp pointer matches tp, return it. + * Otherwise, return NULL. + */ +xfs_inode_t * +xfs_inode_incore(xfs_mount_t *mp, + xfs_ino_t ino, + xfs_trans_t *tp) +{ + xfs_ihash_t *ih; + xfs_inode_t *ip; + + ih = XFS_IHASH(mp, ino); + read_lock(&ih->ih_lock); + for (ip = ih->ih_next; ip != NULL; ip = ip->i_next) { + if (ip->i_ino == ino) { + /* + * If we find it and tp matches, return it. + * Otherwise break from the loop and return + * NULL. + */ + if (ip->i_transp == tp) { + read_unlock(&ih->ih_lock); + return (ip); + } + break; + } + } + read_unlock(&ih->ih_lock); + return (NULL); +} + +/* + * Decrement reference count of an inode structure and unlock it. + * + * ip -- the inode being released + * lock_flags -- this parameter indicates the inode's locks to be + * to be released. See the comment on xfs_iunlock() for a list + * of valid values. + */ +void +xfs_iput(xfs_inode_t *ip, + uint lock_flags) +{ + xfs_vnode_t *vp = XFS_ITOV(ip); + + vn_trace_entry(vp, "xfs_iput", (inst_t *)__return_address); + + xfs_iunlock(ip, lock_flags); + + VN_RELE(vp); +} + +/* + * 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); + + if (lock_flags) + xfs_iunlock(ip, lock_flags); + + VN_RELE(vp); +} + + +/* + * This routine embodies the part of the reclaim code that pulls + * the inode from the inode hash table and the mount structure's + * inode list. + * This should only be called from xfs_reclaim(). + */ +void +xfs_ireclaim(xfs_inode_t *ip) +{ + xfs_vnode_t *vp; + + /* + * Remove from old hash list and mount list. + */ + XFS_STATS_INC(xs_ig_reclaims); + + xfs_iextract(ip); + + /* + * Here we do a spurious inode lock in order to coordinate with + * xfs_sync(). This is because xfs_sync() references the inodes + * in the mount list without taking references on the corresponding + * vnodes. We make that OK here by ensuring that we wait until + * the inode is unlocked in xfs_sync() before we go ahead and + * free it. We get both the regular lock and the io lock because + * the xfs_sync() code may need to drop the regular one but will + * still hold the io lock. + */ + xfs_ilock(ip, XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL); + + /* + * Release dquots (and their references) if any. An inode may escape + * xfs_inactive and get here via vn_alloc->vn_reclaim path. + */ + XFS_QM_DQDETACH(ip->i_mount, ip); + + /* + * Pull our behavior descriptor from the vnode chain. + */ + vp = XFS_ITOV_NULL(ip); + if (vp) { + vn_bhv_remove(VN_BHV_HEAD(vp), XFS_ITOBHV(ip)); + } + + /* + * Free all memory associated with the inode. + */ + xfs_idestroy(ip); +} + +/* + * This routine removes an about-to-be-destroyed inode from + * all of the lists in which it is located with the exception + * of the behavior chain. + */ +void +xfs_iextract( + xfs_inode_t *ip) +{ + xfs_ihash_t *ih; + xfs_inode_t *iq; + xfs_mount_t *mp; + xfs_chash_t *ch; + xfs_chashlist_t *chl, *chm; + SPLDECL(s); + + ih = ip->i_hash; + write_lock(&ih->ih_lock); + if ((iq = ip->i_next)) { + iq->i_prevp = ip->i_prevp; + } + *ip->i_prevp = iq; + write_unlock(&ih->ih_lock); + + /* + * Remove from cluster hash list + * 1) delete the chashlist if this is the last inode on the chashlist + * 2) unchain from list of inodes + * 3) point chashlist->chl_ip to 'chl_next' if to this inode. + */ + mp = ip->i_mount; + ch = XFS_CHASH(mp, ip->i_blkno); + s = mutex_spinlock(&ch->ch_lock); + + if (ip->i_cnext == ip) { + /* Last inode on chashlist */ + ASSERT(ip->i_cnext == ip && ip->i_cprev == ip); + ASSERT(ip->i_chash != NULL); + chm=NULL; + for (chl = ch->ch_list; chl != NULL; chl = chl->chl_next) { + if (chl->chl_blkno == ip->i_blkno) { + if (chm == NULL) { + /* first item on the list */ + ch->ch_list = chl->chl_next; + } else { + chm->chl_next = chl->chl_next; + } + kmem_zone_free(xfs_chashlist_zone, chl); + break; + } else { + ASSERT(chl->chl_ip != ip); + chm = chl; + } + } + ASSERT_ALWAYS(chl != NULL); + } else { + /* delete one inode from a non-empty list */ + iq = ip->i_cnext; + iq->i_cprev = ip->i_cprev; + ip->i_cprev->i_cnext = iq; + if (ip->i_chash->chl_ip == ip) { + ip->i_chash->chl_ip = iq; + } + ip->i_chash = __return_address; + ip->i_cprev = __return_address; + ip->i_cnext = __return_address; + } + mutex_spinunlock(&ch->ch_lock, s); + + /* + * Remove from mount's inode list. + */ + XFS_MOUNT_ILOCK(mp); + ASSERT((ip->i_mnext != NULL) && (ip->i_mprev != NULL)); + iq = ip->i_mnext; + iq->i_mprev = ip->i_mprev; + ip->i_mprev->i_mnext = iq; + + /* + * Fix up the head pointer if it points to the inode being deleted. + */ + if (mp->m_inodes == ip) { + if (ip == iq) { + mp->m_inodes = NULL; + } else { + mp->m_inodes = iq; + } + } + +#if XXXKAN + /* + * Not sure if while i_reclaim crap is needed on + * FreeBSD, will revisit this later. + */ + + /* Deal with the deleted inodes list */ + list_del_init(&ip->i_reclaim); +#endif + + mp->m_ireclaims++; + XFS_MOUNT_IUNLOCK(mp); +} + +/* + * This is a wrapper routine around the xfs_ilock() routine + * used to centralize some grungy code. It is used in places + * that wish to lock the inode solely for reading the extents. + * The reason these places can't just call xfs_ilock(SHARED) + * is that the inode lock also guards to bringing in of the + * extents from disk for a file in b-tree format. If the inode + * is in b-tree format, then we need to lock the inode exclusively + * until the extents are read in. Locking it exclusively all + * the time would limit our parallelism unnecessarily, though. + * What we do instead is check to see if the extents have been + * read in yet, and only lock the inode exclusively if they + * have not. + * + * The function returns a value which should be given to the + * corresponding xfs_iunlock_map_shared(). This value is + * the mode in which the lock was actually taken. + */ +uint +xfs_ilock_map_shared( + xfs_inode_t *ip) +{ + uint lock_mode; + + if ((ip->i_d.di_format == XFS_DINODE_FMT_BTREE) && + ((ip->i_df.if_flags & XFS_IFEXTENTS) == 0)) { + lock_mode = XFS_ILOCK_EXCL; + } else { + lock_mode = XFS_ILOCK_SHARED; + } + + xfs_ilock(ip, lock_mode); + + return lock_mode; +} + +/* + * This is simply the unlock routine to go with xfs_ilock_map_shared(). + * All it does is call xfs_iunlock() with the given lock_mode. + */ +void +xfs_iunlock_map_shared( + xfs_inode_t *ip, + unsigned int lock_mode) +{ + xfs_iunlock(ip, lock_mode); +} + +/* + * The xfs inode contains 2 locks: a multi-reader lock called the + * i_iolock and a multi-reader lock called the i_lock. This routine + * allows either or both of the locks to be obtained. + * + * The 2 locks should always be ordered so that the IO lock is + * obtained first in order to prevent deadlock. + * + * ip -- the inode being locked + * lock_flags -- this parameter indicates the inode's locks + * to be locked. It can be: + * XFS_IOLOCK_SHARED, + * XFS_IOLOCK_EXCL, + * XFS_ILOCK_SHARED, + * XFS_ILOCK_EXCL, + * XFS_IOLOCK_SHARED | XFS_ILOCK_SHARED, + * XFS_IOLOCK_SHARED | XFS_ILOCK_EXCL, + * XFS_IOLOCK_EXCL | XFS_ILOCK_SHARED, + * XFS_IOLOCK_EXCL | XFS_ILOCK_EXCL + */ +void +xfs_ilock(xfs_inode_t *ip, + uint lock_flags) +{ + /* + * You can't set both SHARED and EXCL for the same lock, + * and only XFS_IOLOCK_SHARED, XFS_IOLOCK_EXCL, XFS_ILOCK_SHARED, + * and XFS_ILOCK_EXCL are valid values to set in lock_flags. + */ + ASSERT((lock_flags & (XFS_IOLOCK_SHARED | XFS_IOLOCK_EXCL)) != + (XFS_IOLOCK_SHARED | XFS_IOLOCK_EXCL)); + ASSERT((lock_flags & (XFS_ILOCK_SHARED | XFS_ILOCK_EXCL)) != + (XFS_ILOCK_SHARED | XFS_ILOCK_EXCL)); + ASSERT((lock_flags & ~XFS_LOCK_MASK) == 0); + + if (lock_flags & XFS_IOLOCK_EXCL) { + mrupdate(&ip->i_iolock); + } else if (lock_flags & XFS_IOLOCK_SHARED) { + mraccess(&ip->i_iolock); + } + if (lock_flags & XFS_ILOCK_EXCL) { + mrupdate(&ip->i_lock); + } else if (lock_flags & XFS_ILOCK_SHARED) { + mraccess(&ip->i_lock); + } + xfs_ilock_trace(ip, 1, lock_flags, (inst_t *)__return_address); +} + +/* + * This is just like xfs_ilock(), except that the caller + * is guaranteed not to sleep. It returns 1 if it gets + * the requested locks and 0 otherwise. If the IO lock is + * obtained but the inode lock cannot be, then the IO lock + * is dropped before returning. + * + * ip -- the inode being locked + * lock_flags -- this parameter indicates the inode's locks to be + * to be locked. See the comment for xfs_ilock() for a list + * of valid values. + * + */ +int +xfs_ilock_nowait(xfs_inode_t *ip, + uint lock_flags) +{ + int iolocked; + int ilocked; + + /* + * You can't set both SHARED and EXCL for the same lock, + * and only XFS_IOLOCK_SHARED, XFS_IOLOCK_EXCL, XFS_ILOCK_SHARED, + * and XFS_ILOCK_EXCL are valid values to set in lock_flags. + */ + ASSERT((lock_flags & (XFS_IOLOCK_SHARED | XFS_IOLOCK_EXCL)) != + (XFS_IOLOCK_SHARED | XFS_IOLOCK_EXCL)); + ASSERT((lock_flags & (XFS_ILOCK_SHARED | XFS_ILOCK_EXCL)) != + (XFS_ILOCK_SHARED | XFS_ILOCK_EXCL)); + ASSERT((lock_flags & ~XFS_LOCK_MASK) == 0); + + iolocked = 0; + if (lock_flags & XFS_IOLOCK_EXCL) { + iolocked = mrtryupdate(&ip->i_iolock); + if (!iolocked) { + return 0; + } + } else if (lock_flags & XFS_IOLOCK_SHARED) { + iolocked = mrtryaccess(&ip->i_iolock); + if (!iolocked) { + return 0; + } + } + if (lock_flags & XFS_ILOCK_EXCL) { + ilocked = mrtryupdate(&ip->i_lock); + if (!ilocked) { + if (iolocked) { + mrunlock(&ip->i_iolock); + } + return 0; + } + } else if (lock_flags & XFS_ILOCK_SHARED) { + ilocked = mrtryaccess(&ip->i_lock); + if (!ilocked) { + if (iolocked) { + mrunlock(&ip->i_iolock); + } + return 0; + } + } + xfs_ilock_trace(ip, 2, lock_flags, (inst_t *)__return_address); + return 1; +} + +/* + * xfs_iunlock() is used to drop the inode locks acquired with + * xfs_ilock() and xfs_ilock_nowait(). The caller must pass + * in the flags given to xfs_ilock() or xfs_ilock_nowait() so + * that we know which locks to drop. + * + * ip -- the inode being unlocked + * lock_flags -- this parameter indicates the inode's locks to be + * to be unlocked. See the comment for xfs_ilock() for a list + * of valid values for this parameter. + * + */ +void +xfs_iunlock(xfs_inode_t *ip, + uint lock_flags) +{ + /* + * You can't set both SHARED and EXCL for the same lock, + * and only XFS_IOLOCK_SHARED, XFS_IOLOCK_EXCL, XFS_ILOCK_SHARED, + * and XFS_ILOCK_EXCL are valid values to set in lock_flags. + */ + ASSERT((lock_flags & (XFS_IOLOCK_SHARED | XFS_IOLOCK_EXCL)) != + (XFS_IOLOCK_SHARED | XFS_IOLOCK_EXCL)); + ASSERT((lock_flags & (XFS_ILOCK_SHARED | XFS_ILOCK_EXCL)) != + (XFS_ILOCK_SHARED | XFS_ILOCK_EXCL)); + ASSERT((lock_flags & ~(XFS_LOCK_MASK | XFS_IUNLOCK_NONOTIFY)) == 0); + ASSERT(lock_flags != 0); + + if (lock_flags & (XFS_IOLOCK_SHARED | XFS_IOLOCK_EXCL)) { + ASSERT(!(lock_flags & XFS_IOLOCK_SHARED) || + (ismrlocked(&ip->i_iolock, MR_ACCESS))); + ASSERT(!(lock_flags & XFS_IOLOCK_EXCL) || + (ismrlocked(&ip->i_iolock, MR_UPDATE))); + mrunlock(&ip->i_iolock); + } + + if (lock_flags & (XFS_ILOCK_SHARED | XFS_ILOCK_EXCL)) { + ASSERT(!(lock_flags & XFS_ILOCK_SHARED) || + (ismrlocked(&ip->i_lock, MR_ACCESS))); + ASSERT(!(lock_flags & XFS_ILOCK_EXCL) || + (ismrlocked(&ip->i_lock, MR_UPDATE))); + mrunlock(&ip->i_lock); + + /* + * Let the AIL know that this item has been unlocked in case + * it is in the AIL and anyone is waiting on it. Don't do + * this if the caller has asked us not to. + */ + if (!(lock_flags & XFS_IUNLOCK_NONOTIFY) && + ip->i_itemp != NULL) { + xfs_trans_unlocked_item(ip->i_mount, + (xfs_log_item_t*)(ip->i_itemp)); + } + } + xfs_ilock_trace(ip, 3, lock_flags, (inst_t *)__return_address); +} + +/* + * give up write locks. the i/o lock cannot be held nested + * if it is being demoted. + */ +void +xfs_ilock_demote(xfs_inode_t *ip, + uint lock_flags) +{ + ASSERT(lock_flags & (XFS_IOLOCK_EXCL|XFS_ILOCK_EXCL)); + ASSERT((lock_flags & ~(XFS_IOLOCK_EXCL|XFS_ILOCK_EXCL)) == 0); + + if (lock_flags & XFS_ILOCK_EXCL) { + ASSERT(ismrlocked(&ip->i_lock, MR_UPDATE)); + mrdemote(&ip->i_lock); + } + if (lock_flags & XFS_IOLOCK_EXCL) { + ASSERT(ismrlocked(&ip->i_iolock, MR_UPDATE)); + mrdemote(&ip->i_iolock); + } +} + +/* + * The following three routines simply manage the i_flock + * semaphore embedded in the inode. This semaphore synchronizes + * processes attempting to flush the in-core inode back to disk. + */ +void +xfs_iflock(xfs_inode_t *ip) +{ + psema(&(ip->i_flock), PINOD|PLTWAIT); +} + +int +xfs_iflock_nowait(xfs_inode_t *ip) +{ + return (cpsema(&(ip->i_flock))); +} + +void +xfs_ifunlock(xfs_inode_t *ip) +{ + ASSERT(valusema(&(ip->i_flock)) <= 0); + vsema(&(ip->i_flock)); +} + +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); + } + + vp->v_vnlock->lk_flags |= LK_CANRECURSE; + vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, curthread); + + vp->v_data = (void *)vdata; + vdata->v_number= 0; + vdata->v_inode = ip; + vdata->v_vfsp = XFS_MTOVFS(mp); + vdata->v_vnode = vp; + vdata->v_type = vp->v_type = VNON; + + 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); +} diff --git a/sys/gnu/fs/xfs/FreeBSD/xfs_ioctl.c b/sys/gnu/fs/xfs/FreeBSD/xfs_ioctl.c new file mode 100644 index 0000000..40c3159 --- /dev/null +++ b/sys/gnu/fs/xfs/FreeBSD/xfs_ioctl.c @@ -0,0 +1,1244 @@ +/* + * 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_fs.h" +#include "xfs_inum.h" +#include "xfs_log.h" +#include "xfs_trans.h" +#include "xfs_sb.h" +#include "xfs_dir.h" +#include "xfs_dir2.h" +#include "xfs_alloc.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_ialloc.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_bmap.h" +#include "xfs_bit.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_dfrag.h" +#include "xfs_fsops.h" + + +#if XXXKAN +/* + * ioctl commands that are used by Linux filesystems + */ +#define XFS_IOC_GETXFLAGS _IOR('f', 1, long) +#define XFS_IOC_SETXFLAGS _IOW('f', 2, long) +#define XFS_IOC_GETVERSION _IOR('v', 1, long) + + +/* + * xfs_find_handle maps from userspace xfs_fsop_handlereq structure to + * a file or fs handle. + * + * XFS_IOC_PATH_TO_FSHANDLE + * returns fs handle for a mount point or path within that mount point + * XFS_IOC_FD_TO_HANDLE + * returns full handle for a FD opened in user space + * XFS_IOC_PATH_TO_HANDLE + * returns full handle for a path + */ +STATIC int +xfs_find_handle( + unsigned int cmd, + unsigned long arg) +{ + int hsize; + xfs_handle_t handle; + xfs_fsop_handlereq_t hreq; + struct xfs_vnode *vp; + struct thread *td = curthread; + + if (copy_from_user(&hreq, (xfs_fsop_handlereq_t *)arg, sizeof(hreq))) + return XFS_ERROR(EFAULT); + + memset((char *)&handle, 0, sizeof(handle)); + + switch (cmd) { + case XFS_IOC_PATH_TO_FSHANDLE: + case XFS_IOC_PATH_TO_HANDLE: { + struct nameidata nd; + int error; + + NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | NOOBJ, + UIO_USERSPACE, hreq.path, td); + error = namei(&nd); + if (error) + return error; + NDFREE(&nd, NDF_ONLY_PNBUF); + break; + } + + case XFS_IOC_FD_TO_HANDLE: { + struct file *file; + + error = getvnode(td->td_proc->p_fd, hreq.fd, &file); + if (error) + return error; + + error = vget(vp, LK_EXCLUSIVE, td); + if (error) { + fdrop(file); + return error; + } + fdrop(file); + break; + } + + default: + ASSERT(0); + return XFS_ERROR(EINVAL); + } + + if (inode->i_sb->s_magic != XFS_SB_MAGIC) { + /* we're not in XFS anymore, Toto */ + iput(inode); + return XFS_ERROR(EINVAL); + } + + /* we need the vnode */ + vp = LINVFS_GET_VP(inode); + if (vp->v_type != VREG && vp->v_type != VDIR && vp->v_type != VLNK) { + iput(inode); + return XFS_ERROR(EBADF); + } + + /* now we can grab the fsid */ + memcpy(&handle.ha_fsid, vp->v_vfsp->vfs_altfsid, sizeof(xfs_fsid_t)); + hsize = sizeof(xfs_fsid_t); + + if (cmd != XFS_IOC_PATH_TO_FSHANDLE) { + xfs_inode_t *ip; + bhv_desc_t *bhv; + int lock_mode; + + /* need to get access to the xfs_inode to read the generation */ + bhv = vn_bhv_lookup_unlocked(VN_BHV_HEAD(vp), &xfs_vnodeops); + ASSERT(bhv); + ip = XFS_BHVTOI(bhv); + ASSERT(ip); + lock_mode = xfs_ilock_map_shared(ip); + + /* fill in fid section of handle from inode */ + handle.ha_fid.xfs_fid_len = sizeof(xfs_fid_t) - + sizeof(handle.ha_fid.xfs_fid_len); + handle.ha_fid.xfs_fid_pad = 0; + handle.ha_fid.xfs_fid_gen = ip->i_d.di_gen; + handle.ha_fid.xfs_fid_ino = ip->i_ino; + + xfs_iunlock_map_shared(ip, lock_mode); + + hsize = XFS_HSIZE(handle); + } + + /* now copy our handle into the user buffer & write out the size */ + if (copy_to_user((xfs_handle_t *)hreq.ohandle, &handle, hsize) || + copy_to_user(hreq.ohandlen, &hsize, sizeof(__s32))) { + iput(inode); + return -XFS_ERROR(EFAULT); + } + + iput(inode); + return 0; +} + + +/* + * Convert userspace handle data into vnode (and inode). + * We [ab]use the fact that all the fsop_handlereq ioctl calls + * have a data structure argument whose first component is always + * a xfs_fsop_handlereq_t, so we can cast to and from this type. + * This allows us to optimise the copy_from_user calls and gives + * a handy, shared routine. + * + * If no error, caller must always VN_RELE the returned vp. + */ +STATIC int +xfs_vget_fsop_handlereq( + xfs_mount_t *mp, + struct inode *parinode, /* parent inode pointer */ + int cap, /* capability level for op */ + unsigned long arg, /* userspace data pointer */ + unsigned long size, /* size of expected struct */ + /* output arguments */ + xfs_fsop_handlereq_t *hreq, + vnode_t **vp, + struct inode **inode) +{ + void *hanp; + size_t hlen; + xfs_fid_t *xfid; + xfs_handle_t *handlep; + xfs_handle_t handle; + xfs_inode_t *ip; + struct inode *inodep; + vnode_t *vpp; + xfs_ino_t ino; + __u32 igen; + int error; + + if (!capable(cap)) + return XFS_ERROR(EPERM); + + /* + * Only allow handle opens under a directory. + */ + if (!S_ISDIR(parinode->i_mode)) + return XFS_ERROR(ENOTDIR); + + /* + * Copy the handle down from the user and validate + * that it looks to be in the correct format. + */ + if (copy_from_user(hreq, (struct xfs_fsop_handlereq *)arg, size)) + return XFS_ERROR(EFAULT); + + hanp = hreq->ihandle; + hlen = hreq->ihandlen; + handlep = &handle; + + if (hlen < sizeof(handlep->ha_fsid) || hlen > sizeof(*handlep)) + return XFS_ERROR(EINVAL); + if (copy_from_user(handlep, hanp, hlen)) + return XFS_ERROR(EFAULT); + if (hlen < sizeof(*handlep)) + memset(((char *)handlep) + hlen, 0, sizeof(*handlep) - hlen); + if (hlen > sizeof(handlep->ha_fsid)) { + if (handlep->ha_fid.xfs_fid_len != + (hlen - sizeof(handlep->ha_fsid) + - sizeof(handlep->ha_fid.xfs_fid_len)) + || handlep->ha_fid.xfs_fid_pad) + return XFS_ERROR(EINVAL); + } + + /* + * Crack the handle, obtain the inode # & generation # + */ + xfid = (struct xfs_fid *)&handlep->ha_fid; + if (xfid->xfs_fid_len == sizeof(*xfid) - sizeof(xfid->xfs_fid_len)) { + ino = xfid->xfs_fid_ino; + igen = xfid->xfs_fid_gen; + } else { + return XFS_ERROR(EINVAL); + } + + /* + * Get the XFS inode, building a vnode to go with it. + */ + error = xfs_iget(mp, NULL, ino, XFS_ILOCK_SHARED, &ip, 0); + if (error) + return error; + if (ip == NULL) + return XFS_ERROR(EIO); + if (ip->i_d.di_mode == 0 || ip->i_d.di_gen != igen) { + xfs_iput_new(ip, XFS_ILOCK_SHARED); + return XFS_ERROR(ENOENT); + } + + vpp = XFS_ITOV(ip); + inodep = LINVFS_GET_IP(vpp); + xfs_iunlock(ip, XFS_ILOCK_SHARED); + + *vp = vpp; + *inode = inodep; + return 0; +} + +STATIC int +xfs_open_by_handle( + xfs_mount_t *mp, + unsigned long arg, + struct file *parfilp, + struct inode *parinode) +{ + int error; + int new_fd; + int permflag; + struct file *filp; + struct inode *inode; + struct dentry *dentry; + vnode_t *vp; + xfs_fsop_handlereq_t hreq; + + error = xfs_vget_fsop_handlereq(mp, parinode, CAP_SYS_ADMIN, arg, + sizeof(xfs_fsop_handlereq_t), + &hreq, &vp, &inode); + if (error) + return -error; + + /* Restrict xfs_open_by_handle to directories & regular files. */ + if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode))) { + iput(inode); + return -XFS_ERROR(EINVAL); + } + +#if BITS_PER_LONG != 32 + hreq.oflags |= O_LARGEFILE; +#endif + /* Put open permission in namei format. */ + permflag = hreq.oflags; + if ((permflag+1) & O_ACCMODE) + permflag++; + if (permflag & O_TRUNC) + permflag |= 2; + + if ((!(permflag & O_APPEND) || (permflag & O_TRUNC)) && + (permflag & FMODE_WRITE) && IS_APPEND(inode)) { + iput(inode); + return -XFS_ERROR(EPERM); + } + + if ((permflag & FMODE_WRITE) && IS_IMMUTABLE(inode)) { + iput(inode); + return -XFS_ERROR(EACCES); + } + + /* Can't write directories. */ + if ( S_ISDIR(inode->i_mode) && (permflag & FMODE_WRITE)) { + iput(inode); + return -XFS_ERROR(EISDIR); + } + + if ((new_fd = get_unused_fd()) < 0) { + iput(inode); + return new_fd; + } + + dentry = d_alloc_anon(inode); + if (dentry == NULL) { + iput(inode); + put_unused_fd(new_fd); + return -XFS_ERROR(ENOMEM); + } + + /* Ensure umount returns EBUSY on umounts while this file is open. */ + mntget(parfilp->f_vfsmnt); + + /* Create file pointer. */ + filp = dentry_open(dentry, parfilp->f_vfsmnt, hreq.oflags); + if (IS_ERR(filp)) { + put_unused_fd(new_fd); + return -XFS_ERROR(-PTR_ERR(filp)); + } + if (inode->i_mode & S_IFREG) + filp->f_op = &linvfs_invis_file_operations; + + fd_install(new_fd, filp); + return new_fd; +} + +STATIC int +xfs_readlink_by_handle( + xfs_mount_t *mp, + unsigned long arg, + struct file *parfilp, + struct inode *parinode) +{ + int error; + struct iovec aiov; + struct uio auio; + struct inode *inode; + xfs_fsop_handlereq_t hreq; + vnode_t *vp; + __u32 olen; + + error = xfs_vget_fsop_handlereq(mp, parinode, CAP_SYS_ADMIN, arg, + sizeof(xfs_fsop_handlereq_t), + &hreq, &vp, &inode); + if (error) + return -error; + + /* Restrict this handle operation to symlinks only. */ + if (vp->v_type != VLNK) { + VN_RELE(vp); + return -XFS_ERROR(EINVAL); + } + + if (copy_from_user(&olen, hreq.ohandlen, sizeof(__u32))) { + VN_RELE(vp); + return -XFS_ERROR(EFAULT); + } + aiov.iov_len = olen; + aiov.iov_base = hreq.ohandle; + + auio.uio_iov = &aiov; + auio.uio_iovcnt = 1; + auio.uio_offset = 0; + auio.uio_segflg = UIO_USERSPACE; + auio.uio_resid = olen; + + VOP_READLINK(vp, &auio, IO_INVIS, NULL, error); + + VN_RELE(vp); + return (olen - auio.uio_resid); +} + +STATIC int +xfs_fssetdm_by_handle( + xfs_mount_t *mp, + unsigned long arg, + struct file *parfilp, + struct inode *parinode) +{ + int error; + struct fsdmidata fsd; + xfs_fsop_setdm_handlereq_t dmhreq; + struct inode *inode; + bhv_desc_t *bdp; + vnode_t *vp; + + error = xfs_vget_fsop_handlereq(mp, parinode, CAP_MKNOD, arg, + sizeof(xfs_fsop_setdm_handlereq_t), + (xfs_fsop_handlereq_t *)&dmhreq, + &vp, &inode); + if (error) + return -error; + + if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) { + VN_RELE(vp); + return -XFS_ERROR(EPERM); + } + + if (copy_from_user(&fsd, dmhreq.data, sizeof(fsd))) { + VN_RELE(vp); + return -XFS_ERROR(EFAULT); + } + + bdp = bhv_base_unlocked(VN_BHV_HEAD(vp)); + error = xfs_set_dmattrs(bdp, fsd.fsd_dmevmask, fsd.fsd_dmstate, NULL); + + VN_RELE(vp); + if (error) + return -error; + return 0; +} + +STATIC int +xfs_attrlist_by_handle( + xfs_mount_t *mp, + unsigned long arg, + struct file *parfilp, + struct inode *parinode) +{ + int error; + attrlist_cursor_kern_t *cursor; + xfs_fsop_attrlist_handlereq_t al_hreq; + struct inode *inode; + vnode_t *vp; + + error = xfs_vget_fsop_handlereq(mp, parinode, CAP_SYS_ADMIN, arg, + sizeof(xfs_fsop_attrlist_handlereq_t), + (xfs_fsop_handlereq_t *)&al_hreq, + &vp, &inode); + if (error) + return -error; + + cursor = (attrlist_cursor_kern_t *)&al_hreq.pos; + VOP_ATTR_LIST(vp, al_hreq.buffer, al_hreq.buflen, al_hreq.flags, + cursor, NULL, error); + VN_RELE(vp); + if (error) + return -error; + return 0; +} + +STATIC int +xfs_attrmulti_by_handle( + xfs_mount_t *mp, + unsigned long arg, + struct file *parfilp, + struct inode *parinode) +{ + int error; + xfs_attr_multiop_t *ops; + xfs_fsop_attrmulti_handlereq_t am_hreq; + struct inode *inode; + vnode_t *vp; + int i, size; + + error = xfs_vget_fsop_handlereq(mp, parinode, CAP_SYS_ADMIN, arg, + sizeof(xfs_fsop_attrmulti_handlereq_t), + (xfs_fsop_handlereq_t *)&am_hreq, + &vp, &inode); + if (error) + return -error; + + size = am_hreq.opcount * sizeof(attr_multiop_t); + ops = (xfs_attr_multiop_t *)kmalloc(size, GFP_KERNEL); + if (!ops) { + VN_RELE(vp); + return -XFS_ERROR(ENOMEM); + } + + if (copy_from_user(ops, am_hreq.ops, size)) { + kfree(ops); + VN_RELE(vp); + return -XFS_ERROR(EFAULT); + } + + for (i = 0; i < am_hreq.opcount; i++) { + switch(ops[i].am_opcode) { + case ATTR_OP_GET: + VOP_ATTR_GET(vp,ops[i].am_attrname, ops[i].am_attrvalue, + &ops[i].am_length, ops[i].am_flags, + NULL, ops[i].am_error); + break; + case ATTR_OP_SET: + if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) { + ops[i].am_error = EPERM; + break; + } + VOP_ATTR_SET(vp,ops[i].am_attrname, ops[i].am_attrvalue, + ops[i].am_length, ops[i].am_flags, + NULL, ops[i].am_error); + break; + case ATTR_OP_REMOVE: + if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) { + ops[i].am_error = EPERM; + break; + } + VOP_ATTR_REMOVE(vp, ops[i].am_attrname, ops[i].am_flags, + NULL, ops[i].am_error); + break; + default: + ops[i].am_error = EINVAL; + } + } + + if (copy_to_user(am_hreq.ops, ops, size)) + error = -XFS_ERROR(EFAULT); + + kfree(ops); + VN_RELE(vp); + return error; +} + +/* prototypes for a few of the stack-hungry cases that have + * their own functions. Functions are defined after their use + * so gcc doesn't get fancy and inline them with -03 */ + +STATIC int +xfs_ioc_space( + bhv_desc_t *bdp, + vnode_t *vp, + struct file *filp, + int flags, + unsigned int cmd, + unsigned long arg); + +STATIC int +xfs_ioc_bulkstat( + xfs_mount_t *mp, + unsigned int cmd, + unsigned long arg); + +STATIC int +xfs_ioc_fsgeometry_v1( + xfs_mount_t *mp, + unsigned long arg); + +STATIC int +xfs_ioc_fsgeometry( + xfs_mount_t *mp, + unsigned long arg); + +STATIC int +xfs_ioc_xattr( + vnode_t *vp, + xfs_inode_t *ip, + struct file *filp, + unsigned int cmd, + unsigned long arg); + +STATIC int +xfs_ioc_getbmap( + bhv_desc_t *bdp, + struct file *filp, + int flags, + unsigned int cmd, + unsigned long arg); + +STATIC int +xfs_ioc_getbmapx( + bhv_desc_t *bdp, + unsigned long arg); + +int +xfs_ioctl( + bhv_desc_t *bdp, + struct inode *inode, + struct file *filp, + int ioflags, + unsigned int cmd, + unsigned long arg) +{ + int error; + vnode_t *vp; + xfs_inode_t *ip; + xfs_mount_t *mp; + + vp = LINVFS_GET_VP(inode); + + vn_trace_entry(vp, "xfs_ioctl", (inst_t *)__return_address); + + ip = XFS_BHVTOI(bdp); + mp = ip->i_mount; + + switch (cmd) { + + case XFS_IOC_ALLOCSP: + case XFS_IOC_FREESP: + case XFS_IOC_RESVSP: + case XFS_IOC_UNRESVSP: + case XFS_IOC_ALLOCSP64: + case XFS_IOC_FREESP64: + case XFS_IOC_RESVSP64: + case XFS_IOC_UNRESVSP64: + /* + * Only allow the sys admin to reserve space unless + * unwritten extents are enabled. + */ + if (!XFS_SB_VERSION_HASEXTFLGBIT(&mp->m_sb) && + !capable(CAP_SYS_ADMIN)) + return -EPERM; + + return xfs_ioc_space(bdp, vp, filp, ioflags, cmd, arg); + + case XFS_IOC_DIOINFO: { + struct dioattr da; + + da.d_miniosz = mp->m_sb.sb_blocksize; + da.d_mem = mp->m_sb.sb_blocksize; + + /* + * this only really needs to be BBSIZE. + * it is set to the file system block size to + * avoid having to do block zeroing on short writes. + */ + da.d_maxiosz = XFS_FSB_TO_B(mp, + XFS_B_TO_FSBT(mp, KIO_MAX_ATOMIC_IO << 10)); + + if (copy_to_user((struct dioattr *)arg, &da, sizeof(da))) + return -XFS_ERROR(EFAULT); + return 0; + } + + case XFS_IOC_FSBULKSTAT_SINGLE: + case XFS_IOC_FSBULKSTAT: + case XFS_IOC_FSINUMBERS: + return xfs_ioc_bulkstat(mp, cmd, arg); + + case XFS_IOC_FSGEOMETRY_V1: + return xfs_ioc_fsgeometry_v1(mp, arg); + + case XFS_IOC_FSGEOMETRY: + return xfs_ioc_fsgeometry(mp, arg); + + case XFS_IOC_GETVERSION: + case XFS_IOC_GETXFLAGS: + case XFS_IOC_SETXFLAGS: + case XFS_IOC_FSGETXATTR: + case XFS_IOC_FSSETXATTR: + case XFS_IOC_FSGETXATTRA: + return xfs_ioc_xattr(vp, ip, filp, cmd, arg); + + case XFS_IOC_FSSETDM: { + struct fsdmidata dmi; + + if (copy_from_user(&dmi, (struct fsdmidata *)arg, sizeof(dmi))) + return -XFS_ERROR(EFAULT); + + error = xfs_set_dmattrs(bdp, dmi.fsd_dmevmask, dmi.fsd_dmstate, + NULL); + return -error; + } + + case XFS_IOC_GETBMAP: + case XFS_IOC_GETBMAPA: + return xfs_ioc_getbmap(bdp, filp, ioflags, cmd, arg); + + case XFS_IOC_GETBMAPX: + return xfs_ioc_getbmapx(bdp, arg); + + case XFS_IOC_FD_TO_HANDLE: + case XFS_IOC_PATH_TO_HANDLE: + case XFS_IOC_PATH_TO_FSHANDLE: + return xfs_find_handle(cmd, arg); + + case XFS_IOC_OPEN_BY_HANDLE: + return xfs_open_by_handle(mp, arg, filp, inode); + + case XFS_IOC_FSSETDM_BY_HANDLE: + return xfs_fssetdm_by_handle(mp, arg, filp, inode); + + case XFS_IOC_READLINK_BY_HANDLE: + return xfs_readlink_by_handle(mp, arg, filp, inode); + + case XFS_IOC_ATTRLIST_BY_HANDLE: + return xfs_attrlist_by_handle(mp, arg, filp, inode); + + case XFS_IOC_ATTRMULTI_BY_HANDLE: + return xfs_attrmulti_by_handle(mp, arg, filp, inode); + + case XFS_IOC_SWAPEXT: { + error = xfs_swapext((struct xfs_swapext *)arg); + return -error; + } + + case XFS_IOC_FSCOUNTS: { + xfs_fsop_counts_t out; + + error = xfs_fs_counts(mp, &out); + if (error) + return -error; + + if (copy_to_user((char *)arg, &out, sizeof(out))) + return -XFS_ERROR(EFAULT); + return 0; + } + + case XFS_IOC_SET_RESBLKS: { + xfs_fsop_resblks_t inout; + __uint64_t in; + + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + + if (copy_from_user(&inout, (char *)arg, sizeof(inout))) + return -XFS_ERROR(EFAULT); + + /* input parameter is passed in resblks field of structure */ + in = inout.resblks; + error = xfs_reserve_blocks(mp, &in, &inout); + if (error) + return -error; + + if (copy_to_user((char *)arg, &inout, sizeof(inout))) + return -XFS_ERROR(EFAULT); + return 0; + } + + case XFS_IOC_GET_RESBLKS: { + xfs_fsop_resblks_t out; + + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + + error = xfs_reserve_blocks(mp, NULL, &out); + if (error) + return -error; + + if (copy_to_user((char *)arg, &out, sizeof(out))) + return -XFS_ERROR(EFAULT); + + return 0; + } + + case XFS_IOC_FSGROWFSDATA: { + xfs_growfs_data_t in; + + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + + if (copy_from_user(&in, (char *)arg, sizeof(in))) + return -XFS_ERROR(EFAULT); + + error = xfs_growfs_data(mp, &in); + return -error; + } + + case XFS_IOC_FSGROWFSLOG: { + xfs_growfs_log_t in; + + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + + if (copy_from_user(&in, (char *)arg, sizeof(in))) + return -XFS_ERROR(EFAULT); + + error = xfs_growfs_log(mp, &in); + return -error; + } + + case XFS_IOC_FSGROWFSRT: { + xfs_growfs_rt_t in; + + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + + if (copy_from_user(&in, (char *)arg, sizeof(in))) + return -XFS_ERROR(EFAULT); + + error = xfs_growfs_rt(mp, &in); + return -error; + } + + case XFS_IOC_FREEZE: + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + xfs_fs_freeze(mp); + return 0; + + case XFS_IOC_THAW: + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + xfs_fs_thaw(mp); + return 0; + + case XFS_IOC_GOINGDOWN: { + __uint32_t in; + + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + + if (get_user(in, (__uint32_t *)arg)) + return -XFS_ERROR(EFAULT); + + error = xfs_fs_goingdown(mp, in); + return -error; + } + + case XFS_IOC_ERROR_INJECTION: { + xfs_error_injection_t in; + + if (copy_from_user(&in, (char *)arg, sizeof(in))) + return -XFS_ERROR(EFAULT); + + error = xfs_errortag_add(in.errtag, mp); + return -error; + } + + case XFS_IOC_ERROR_CLEARALL: + error = xfs_errortag_clearall(mp); + return -error; + + default: + return -ENOTTY; + } +} + +STATIC int +xfs_ioc_space( + bhv_desc_t *bdp, + vnode_t *vp, + struct file *filp, + int ioflags, + unsigned int cmd, + unsigned long arg) +{ + xfs_flock64_t bf; + int attr_flags = 0; + int error; + + if (vp->v_inode.i_flags & (S_IMMUTABLE|S_APPEND)) + return -XFS_ERROR(EPERM); + + if (filp->f_flags & O_RDONLY) + return -XFS_ERROR(EBADF); + + if (vp->v_type != VREG) + return -XFS_ERROR(EINVAL); + + if (copy_from_user(&bf, (xfs_flock64_t *)arg, sizeof(bf))) + return -XFS_ERROR(EFAULT); + + if (filp->f_flags & (O_NDELAY|O_NONBLOCK)) + attr_flags |= ATTR_NONBLOCK; + if (ioflags & IO_INVIS) + attr_flags |= ATTR_DMI; + + error = xfs_change_file_space(bdp, cmd, &bf, filp->f_pos, + NULL, attr_flags); + return -error; +} + +STATIC int +xfs_ioc_bulkstat( + xfs_mount_t *mp, + unsigned int cmd, + unsigned long arg) +{ + xfs_fsop_bulkreq_t bulkreq; + int count; /* # of records returned */ + xfs_ino_t inlast; /* last inode number */ + int done; + int error; + + /* done = 1 if there are more stats to get and if bulkstat */ + /* should be called again (unused here, but used in dmapi) */ + + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + + if (XFS_FORCED_SHUTDOWN(mp)) + return -XFS_ERROR(EIO); + + if (copy_from_user(&bulkreq, (xfs_fsop_bulkreq_t *)arg, + sizeof(xfs_fsop_bulkreq_t))) + return -XFS_ERROR(EFAULT); + + if (copy_from_user(&inlast, (__s64 *)bulkreq.lastip, + sizeof(__s64))) + return -XFS_ERROR(EFAULT); + + if ((count = bulkreq.icount) <= 0) + return -XFS_ERROR(EINVAL); + + if (cmd == XFS_IOC_FSINUMBERS) + error = xfs_inumbers(mp, NULL, &inlast, &count, + bulkreq.ubuffer); + else if (cmd == XFS_IOC_FSBULKSTAT_SINGLE) + error = xfs_bulkstat_single(mp, &inlast, + bulkreq.ubuffer, &done); + else { /* XFS_IOC_FSBULKSTAT */ + if (count == 1 && inlast != 0) { + inlast++; + error = xfs_bulkstat_single(mp, &inlast, + bulkreq.ubuffer, &done); + } else { + error = xfs_bulkstat(mp, NULL, &inlast, &count, + (bulkstat_one_pf)xfs_bulkstat_one, NULL, + sizeof(xfs_bstat_t), bulkreq.ubuffer, + BULKSTAT_FG_QUICK, &done); + } + } + + if (error) + return -error; + + if (bulkreq.ocount != NULL) { + if (copy_to_user((xfs_ino_t *)bulkreq.lastip, &inlast, + sizeof(xfs_ino_t))) + return -XFS_ERROR(EFAULT); + + if (copy_to_user((__s32 *)bulkreq.ocount, &count, + sizeof(count))) + return -XFS_ERROR(EFAULT); + } + + return 0; +} + +STATIC int +xfs_ioc_fsgeometry_v1( + xfs_mount_t *mp, + unsigned long arg) +{ + xfs_fsop_geom_v1_t fsgeo; + int error; + + error = xfs_fs_geometry(mp, (xfs_fsop_geom_t *)&fsgeo, 3); + if (error) + return -error; + + if (copy_to_user((xfs_fsop_geom_t *)arg, &fsgeo, sizeof(fsgeo))) + return -XFS_ERROR(EFAULT); + return 0; +} + +STATIC int +xfs_ioc_fsgeometry( + xfs_mount_t *mp, + unsigned long arg) +{ + xfs_fsop_geom_t fsgeo; + int error; + + error = xfs_fs_geometry(mp, &fsgeo, 4); + if (error) + return -error; + + if (copy_to_user((xfs_fsop_geom_t *)arg, &fsgeo, sizeof(fsgeo))) + return -XFS_ERROR(EFAULT); + return 0; +} + +/* + * Linux extended inode flags interface. + */ +#define LINUX_XFLAG_SYNC 0x00000008 /* Synchronous updates */ +#define LINUX_XFLAG_IMMUTABLE 0x00000010 /* Immutable file */ +#define LINUX_XFLAG_APPEND 0x00000020 /* writes to file may only append */ +#define LINUX_XFLAG_NODUMP 0x00000040 /* do not dump file */ +#define LINUX_XFLAG_NOATIME 0x00000080 /* do not update atime */ + +STATIC unsigned int +xfs_merge_ioc_xflags( + unsigned int flags, + unsigned int start) +{ + unsigned int xflags = start; + + if (flags & LINUX_XFLAG_IMMUTABLE) + xflags |= XFS_XFLAG_IMMUTABLE; + else + xflags &= ~XFS_XFLAG_IMMUTABLE; + if (flags & LINUX_XFLAG_APPEND) + xflags |= XFS_XFLAG_APPEND; + else + xflags &= ~XFS_XFLAG_APPEND; + if (flags & LINUX_XFLAG_SYNC) + xflags |= XFS_XFLAG_SYNC; + else + xflags &= ~XFS_XFLAG_SYNC; + if (flags & LINUX_XFLAG_NOATIME) + xflags |= XFS_XFLAG_NOATIME; + else + xflags &= ~XFS_XFLAG_NOATIME; + if (flags & LINUX_XFLAG_NODUMP) + xflags |= XFS_XFLAG_NODUMP; + else + xflags &= ~XFS_XFLAG_NODUMP; + + return xflags; +} + +STATIC int +xfs_ioc_xattr( + vnode_t *vp, + xfs_inode_t *ip, + struct file *filp, + unsigned int cmd, + unsigned long arg) +{ + struct fsxattr fa; + vattr_t va; + int error; + int attr_flags; + unsigned int flags; + + switch (cmd) { + case XFS_IOC_FSGETXATTR: { + va.va_mask = XFS_AT_XFLAGS|XFS_AT_EXTSIZE|XFS_AT_NEXTENTS; + VOP_GETATTR(vp, &va, 0, NULL, error); + if (error) + return -error; + + fa.fsx_xflags = va.va_xflags; + fa.fsx_extsize = va.va_extsize; + fa.fsx_nextents = va.va_nextents; + + if (copy_to_user((struct fsxattr *)arg, &fa, sizeof(fa))) + return -XFS_ERROR(EFAULT); + return 0; + } + + case XFS_IOC_FSSETXATTR: { + if (copy_from_user(&fa, (struct fsxattr *)arg, sizeof(fa))) + return -XFS_ERROR(EFAULT); + + attr_flags = 0; + if (filp->f_flags & (O_NDELAY|O_NONBLOCK)) + attr_flags |= ATTR_NONBLOCK; + + va.va_mask = XFS_AT_XFLAGS | XFS_AT_EXTSIZE; + va.va_xflags = fa.fsx_xflags; + va.va_extsize = fa.fsx_extsize; + + VOP_SETATTR(vp, &va, attr_flags, NULL, error); + if (!error) + vn_revalidate(vp); /* update Linux inode flags */ + return -error; + } + + case XFS_IOC_FSGETXATTRA: { + va.va_mask = XFS_AT_XFLAGS|XFS_AT_EXTSIZE|XFS_AT_ANEXTENTS; + VOP_GETATTR(vp, &va, 0, NULL, error); + if (error) + return -error; + + fa.fsx_xflags = va.va_xflags; + fa.fsx_extsize = va.va_extsize; + fa.fsx_nextents = va.va_anextents; + + if (copy_to_user((struct fsxattr *)arg, &fa, sizeof(fa))) + return -XFS_ERROR(EFAULT); + return 0; + } + + case XFS_IOC_GETXFLAGS: { + flags = 0; + if (ip->i_d.di_flags & XFS_XFLAG_IMMUTABLE) + flags |= LINUX_XFLAG_IMMUTABLE; + if (ip->i_d.di_flags & XFS_XFLAG_APPEND) + flags |= LINUX_XFLAG_APPEND; + if (ip->i_d.di_flags & XFS_XFLAG_SYNC) + flags |= LINUX_XFLAG_SYNC; + if (ip->i_d.di_flags & XFS_XFLAG_NOATIME) + flags |= LINUX_XFLAG_NOATIME; + if (ip->i_d.di_flags & XFS_XFLAG_NODUMP) + flags |= LINUX_XFLAG_NODUMP; + if (copy_to_user((unsigned int *)arg, &flags, sizeof(flags))) + return -XFS_ERROR(EFAULT); + return 0; + } + + case XFS_IOC_SETXFLAGS: { + if (copy_from_user(&flags, (unsigned int *)arg, sizeof(flags))) + return -XFS_ERROR(EFAULT); + + if (flags & ~(LINUX_XFLAG_IMMUTABLE | LINUX_XFLAG_APPEND | \ + LINUX_XFLAG_NOATIME | LINUX_XFLAG_NODUMP | \ + LINUX_XFLAG_SYNC)) + return -XFS_ERROR(EOPNOTSUPP); + + attr_flags = 0; + if (filp->f_flags & (O_NDELAY|O_NONBLOCK)) + attr_flags |= ATTR_NONBLOCK; + + va.va_mask = XFS_AT_XFLAGS; + va.va_xflags = xfs_merge_ioc_xflags(flags, ip->i_d.di_flags); + + VOP_SETATTR(vp, &va, attr_flags, NULL, error); + if (!error) + vn_revalidate(vp); /* update Linux inode flags */ + return -error; + } + + case XFS_IOC_GETVERSION: { + flags = LINVFS_GET_IP(vp)->i_generation; + if (copy_to_user((unsigned int *)arg, &flags, sizeof(flags))) + return -XFS_ERROR(EFAULT); + return 0; + } + + default: + return -ENOTTY; + } +} + +STATIC int +xfs_ioc_getbmap( + bhv_desc_t *bdp, + struct file *filp, + int ioflags, + unsigned int cmd, + unsigned long arg) +{ + struct getbmap bm; + int iflags; + int error; + + if (copy_from_user(&bm, (struct getbmap *)arg, sizeof(bm))) + return -XFS_ERROR(EFAULT); + + if (bm.bmv_count < 2) + return -XFS_ERROR(EINVAL); + + iflags = (cmd == XFS_IOC_GETBMAPA ? BMV_IF_ATTRFORK : 0); + if (ioflags & IO_INVIS) + iflags |= BMV_IF_NO_DMAPI_READ; + + error = xfs_getbmap(bdp, &bm, (struct getbmap *)arg+1, iflags); + if (error) + return -error; + + if (copy_to_user((struct getbmap *)arg, &bm, sizeof(bm))) + return -XFS_ERROR(EFAULT); + return 0; +} + +STATIC int +xfs_ioc_getbmapx( + bhv_desc_t *bdp, + unsigned long arg) +{ + struct getbmapx bmx; + struct getbmap bm; + int iflags; + int error; + + if (copy_from_user(&bmx, (struct getbmapx *)arg, sizeof(bmx))) + return -XFS_ERROR(EFAULT); + + if (bmx.bmv_count < 2) + return -XFS_ERROR(EINVAL); + + /* + * Map input getbmapx structure to a getbmap + * structure for xfs_getbmap. + */ + GETBMAP_CONVERT(bmx, bm); + + iflags = bmx.bmv_iflags; + + if (iflags & (~BMV_IF_VALID)) + return -XFS_ERROR(EINVAL); + + iflags |= BMV_IF_EXTENDED; + + error = xfs_getbmap(bdp, &bm, (struct getbmapx *)arg+1, iflags); + if (error) + return -error; + + GETBMAP_CONVERT(bm, bmx); + + if (copy_to_user((struct getbmapx *)arg, &bmx, sizeof(bmx))) + return -XFS_ERROR(EFAULT); + + return 0; +} + +#endif + +int +xfs_ioctl( + bhv_desc_t *bdp, + struct inode *inode, + struct file *filp, + int ioflags, + unsigned int cmd, + unsigned long arg) +{ + return EINVAL; +} diff --git a/sys/gnu/fs/xfs/FreeBSD/xfs_iops.h b/sys/gnu/fs/xfs/FreeBSD/xfs_iops.h new file mode 100644 index 0000000..20549a7 --- /dev/null +++ b/sys/gnu/fs/xfs/FreeBSD/xfs_iops.h @@ -0,0 +1,60 @@ +/* + * 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, unsigned int, unsigned long); +#endif /* __XFS_IOPS_H__ */ diff --git a/sys/gnu/fs/xfs/FreeBSD/xfs_mountops.c b/sys/gnu/fs/xfs/FreeBSD/xfs_mountops.c new file mode 100644 index 0000000..78a091f --- /dev/null +++ b/sys/gnu/fs/xfs/FreeBSD/xfs_mountops.c @@ -0,0 +1,459 @@ +#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_macros.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_alloc_btree.h" +#include "xfs_bmap_btree.h" +#include "xfs_ialloc_btree.h" +#include "xfs_btree.h" +#include "xfs_ialloc.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_alloc.h" +#include "xfs_rtalloc.h" +#include "xfs_bmap.h" +#include "xfs_error.h" +#include "xfs_bit.h" +#include "xfs_rw.h" +#include "xfs_quota.h" +#include "xfs_fsops.h" +#include "xfs_clnt.h" + +#include <xfs_mountops.h> + +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_checkexp_t _xfs_checkexp; +static vfs_vptofh_t _xfs_vptofh; +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", + 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) + return error; + + args->flags |= XFSMNT_32BITINODES; + + parse_int(mp, "sunit", &args->sunit, &error); + if (error != 0) + return error; + + parse_int(mp, "swidth", &args->swidth, &error); + if (error != 0) + return error; + + parse_int(mp, "logbufs", &args->logbufs, &error); + if (error != 0) + return error; + + parse_int(mp, "logbufsize", &args->logbufsize, &error); + if (error != 0) + 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 thread *td) +{ + struct xfsmount *xmp; + struct xfs_vnode *rootvp; + struct ucred *curcred; + struct vnode *rvp; + struct cdev *ddev; + int error; + + if (vfs_filteropt(mp->mnt_optnew, xfs_opts)) + return (EINVAL); + + xmp = xfsmount_allocate(mp); + if (xmp == NULL) + return (ENOMEM); + + if((error = _xfs_param_copyin(mp, td)) != 0) + goto fail; + + /* Force read-only mounts in this branch. */ + XFSTOVFS(xmp)->vfs_flag |= VFS_RDONLY; + mp->mnt_flag |= MNT_RDONLY; + + /* XXX: Do not support MNT_UPDATE yet */ + if (mp->mnt_flag & MNT_UPDATE) + return EOPNOTSUPP; + + curcred = td->td_ucred; + XVFS_MOUNT(XFSTOVFS(xmp), &xmp->m_args, curcred, error); + if (error) + goto fail; + + XVFS_ROOT(XFSTOVFS(xmp), &rootvp, error); + if (error) + goto fail_unmount; + + ddev = XFS_VFSTOM(XFSTOVFS(xmp))->m_dev; + 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 | MNT_RDONLY; + mp->mnt_stat.f_fsid.val[0] = dev2udev(ddev); + mp->mnt_stat.f_fsid.val[1] = mp->mnt_vfc->vfc_typenum; + + VFS_STATFS(mp, &mp->mnt_stat, td); + if (error) + 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); + + fail: + if (xmp != NULL) + xfsmount_deallocate(xmp); + + return (error); +} + +/* + * Free reference to null layer + */ +static int +_xfs_unmount(mp, mntflags, td) + struct mount *mp; + int mntflags; + struct thread *td; +{ + int error; + + XVFS_UNMOUNT(MNTTOVFS(mp), 0, td->td_ucred, error); + return (error); +} + +static int +_xfs_root(mp, flags, vpp, td) + struct mount *mp; + int flags; + struct vnode **vpp; + struct thread *td; +{ + xfs_vnode_t *vp; + int error; + + XVFS_ROOT(MNTTOVFS(mp), &vp, error); + if (error == 0) { + *vpp = vp->v_vnode; + VOP_LOCK(*vpp, flags, curthread); + } + return (error); +} + +static int +_xfs_quotactl(mp, cmd, uid, arg, td) + struct mount *mp; + int cmd; + uid_t uid; + caddr_t arg; + struct thread *td; +{ + printf("xfs_quotactl\n"); + return ENOSYS; +} + +static int +_xfs_statfs(mp, sbp, td) + struct mount *mp; + struct statfs *sbp; + struct thread *td; +{ + 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, td) + struct mount *mp; + int waitfor; + struct thread *td; +{ + 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, td->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; + 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, vpp) + struct mount *mp; + struct fid *fidp; + struct vnode **vpp; +{ + printf("xfs_fhtovp\n"); + return ENOSYS; +} + +static int +_xfs_checkexp(mp, nam, extflagsp, credanonp) + struct mount *mp; + struct sockaddr *nam; + int *extflagsp; + struct ucred **credanonp; +{ + printf("xfs_checkexp\n"); + return ENOSYS; +} + +static int +_xfs_vptofh(vp, fhp) + struct vnode *vp; + struct fid *fhp; +{ + printf("xfs_vptofh"); + return ENOSYS; +} + +static int +_xfs_extattrctl(struct mount *mp, int cm, + struct vnode *filename_v, + int attrnamespace, const char *attrname, + struct thread *td) +{ + 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_checkexp = _xfs_checkexp, + .vfs_vptofh = _xfs_vptofh, + .vfs_init = _xfs_init, + .vfs_uninit = _xfs_uninit, + .vfs_extattrctl = _xfs_extattrctl, +}; + +/* XXX: Read-only for now */ +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); +} + +struct buf_ops xfs_ops = { + .bop_name = "XFS", + .bop_write = xfs_geom_bufwrite, + .bop_strategy = xfs_geom_strategy, + .bop_sync = bufsync, +}; diff --git a/sys/gnu/fs/xfs/FreeBSD/xfs_mountops.h b/sys/gnu/fs/xfs/FreeBSD/xfs_mountops.h new file mode 100644 index 0000000..c8a766d --- /dev/null +++ b/sys/gnu/fs/xfs/FreeBSD/xfs_mountops.h @@ -0,0 +1,59 @@ +/*- + * 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*/ + diff --git a/sys/gnu/fs/xfs/FreeBSD/xfs_node.h b/sys/gnu/fs/xfs/FreeBSD/xfs_node.h new file mode 100644 index 0000000..d8b613c --- /dev/null +++ b/sys/gnu/fs/xfs/FreeBSD/xfs_node.h @@ -0,0 +1,16 @@ +#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__ */ diff --git a/sys/gnu/fs/xfs/FreeBSD/xfs_stats.c b/sys/gnu/fs/xfs/FreeBSD/xfs_stats.c new file mode 100644 index 0000000..04582ee --- /dev/null +++ b/sys/gnu/fs/xfs/FreeBSD/xfs_stats.c @@ -0,0 +1,105 @@ +/* + * 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, 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) +{ +} diff --git a/sys/gnu/fs/xfs/FreeBSD/xfs_stats.h b/sys/gnu/fs/xfs/FreeBSD/xfs_stats.h new file mode 100644 index 0000000..04ddc95 --- /dev/null +++ b/sys/gnu/fs/xfs/FreeBSD/xfs_stats.h @@ -0,0 +1,161 @@ +/* + * 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__ */ + diff --git a/sys/gnu/fs/xfs/FreeBSD/xfs_super.c b/sys/gnu/fs/xfs/FreeBSD/xfs_super.c new file mode 100644 index 0000000..7f23f42 --- /dev/null +++ b/sys/gnu/fs/xfs/FreeBSD/xfs_super.c @@ -0,0 +1,338 @@ +/* + * Copyright (c) 2000-2004 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_inum.h" +#include "xfs_log.h" +#include "xfs_clnt.h" +#include "xfs_trans.h" +#include "xfs_sb.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_alloc_btree.h" +#include "xfs_bmap_btree.h" +#include "xfs_ialloc_btree.h" +#include "xfs_btree.h" +#include "xfs_ialloc.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_bmap.h" +#include "xfs_bit.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 <geom/geom.h> +#include <geom/geom_vfs.h> + +extern struct vop_vector xfs_fifoops; +extern struct buf_ops xfs_ops; + +__uint64_t +xfs_max_file_offset( + unsigned int blockshift) +{ + + return (OFF_MAX); +} + +void +xfs_initialize_vnode( + bhv_desc_t *bdp, + xfs_vnode_t *vp, + bhv_desc_t *inode_bhv, + int unlock) +{ + xfs_inode_t *ip = XFS_BHVTOI(inode_bhv); + + if (!inode_bhv->bd_vobj) { + vp->v_vfsp = bhvtovfs(bdp); + bhv_desc_init(inode_bhv, ip, vp, &xfs_vnodeops); + bhv_insert(VN_BHV_HEAD(vp), 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 (vp->v_type != VNON) + return; + + vp->v_type = IFTOVT(ip->i_d.di_mode); + vp->v_vnode->v_type = vp->v_type; + + if (vp->v_type == VFIFO) + vp->v_vnode->v_op = &xfs_fifoops; + + ASSERT_VOP_LOCKED(vp->v_vnode, "xfs_initialize_vnode"); + + /* For new inodes we need to set the ops vectors, + * and unlock the inode. + */ + if (unlock) + VOP_UNLOCK(vp->v_vnode, 0, curthread); +} + +struct vnode * +xfs_get_inode( + bhv_desc_t *bdp, + xfs_ino_t ino, + int flags) +{ + return NULL; +} + +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); +} + +/*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; + mode_t accessmode; + + 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, td); + + ronly = ((XFS_MTOVFS(mp)->vfs_flag & VFS_RDONLY) != 0); + if (suser(td)) { + accessmode = VREAD; + if (!ronly) + accessmode |= VWRITE; + if ((error = VOP_ACCESS(devvp, accessmode, td->td_ucred, td))!= 0){ + 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(); + + VOP_UNLOCK(devvp, 0, td); + if (error) { + vput(devvp); + return (error); + } + + devvp->v_bufobj.bo_private = cp; + devvp->v_bufobj.bo_ops = &xfs_ops; + + *bdevp = devvp; + return (0); +} + +void +xfs_blkdev_put( + struct vnode *devvp) +{ + struct g_consumer *cp; + + if (devvp == NULL) + return; + + vinvalbuf(devvp, V_SAVE, curthread, 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_flush_buftarg( + xfs_buftarg_t *btp) +{ + printf("xfs_flush_buftarg NI %p\n",btp); +} + +void +xfs_free_buftarg( + xfs_buftarg_t *btp) +{ + xfs_flush_buftarg(btp); + 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_ops, + ("Bogus xfs_buftarg_t pointer")); + cp = btp->specvp->v_bufobj.bo_private; + + return (cp->acw == 0); +} + +void +xfs_relse_buftarg( + xfs_buftarg_t *btp) +{ + printf("xfs_readonly_buftarg NI %p\n",btp); +} + +unsigned int +xfs_getsize_buftarg( + xfs_buftarg_t *btp) +{ + struct g_consumer *cp; + cp = btp->specvp->v_bufobj.bo_private; + return (cp->provider->sectorsize); +} + +void +xfs_setsize_buftarg( + xfs_buftarg_t *btp, + unsigned int blocksize, + unsigned int sectorsize) +{ + printf("xfs_setsize_buftarg NI %p\n",btp); +} + +xfs_buftarg_t * +xfs_alloc_buftarg( + struct vnode *bdev) +{ + xfs_buftarg_t *btp; + + btp = kmem_zalloc(sizeof(*btp), KM_SLEEP); + + btp->dev = bdev->v_rdev; + btp->specvp = bdev; + + return btp; +} + +int +init_xfs_fs( void ) +{ + static char message[] = + XFS_VERSION_STRING " with " XFS_BUILD_OPTIONS " enabled\n"; + + printf(message); + + vn_init(); + xfs_init(); + uuid_init(); + vfs_initdmapi(); + vfs_initquota(); + + return 0; +} + +void +exit_xfs_fs(void) +{ + xfs_cleanup(); + vfs_exitquota(); + vfs_exitdmapi(); + uuid_cleanup(); +} + diff --git a/sys/gnu/fs/xfs/FreeBSD/xfs_super.h b/sys/gnu/fs/xfs/FreeBSD/xfs_super.h new file mode 100644 index 0000000..2665806 --- /dev/null +++ b/sys/gnu/fs/xfs/FreeBSD/xfs_super.h @@ -0,0 +1,134 @@ +/* + * 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_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 struct vnode * xfs_get_inode( bhv_desc_t *, xfs_ino_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 struct xfs_buftarg *xfs_alloc_buftarg(struct vnode *); +extern void xfs_relse_buftarg(struct xfs_buftarg *); +extern void xfs_free_buftarg(struct xfs_buftarg *); +extern void xfs_flush_buftarg(struct xfs_buftarg *); +extern int xfs_readonly_buftarg(struct xfs_buftarg *); +extern void xfs_setsize_buftarg(struct xfs_buftarg *, unsigned int, unsigned int); +extern unsigned int xfs_getsize_buftarg(struct xfs_buftarg *); + +extern int init_xfs_fs(void); +extern void exit_xfs_fs(void); + +#endif /* __XFS_SUPER_H__ */ + diff --git a/sys/gnu/fs/xfs/FreeBSD/xfs_sysctl.c b/sys/gnu/fs/xfs/FreeBSD/xfs_sysctl.c new file mode 100644 index 0000000..9ba2d45 --- /dev/null +++ b/sys/gnu/fs/xfs/FreeBSD/xfs_sysctl.c @@ -0,0 +1,43 @@ +/* + * 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) +{ +} diff --git a/sys/gnu/fs/xfs/FreeBSD/xfs_sysctl.h b/sys/gnu/fs/xfs/FreeBSD/xfs_sysctl.h new file mode 100644 index 0000000..b4b58b4 --- /dev/null +++ b/sys/gnu/fs/xfs/FreeBSD/xfs_sysctl.h @@ -0,0 +1,118 @@ +/* + * 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/ + */ + +#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 bit if process' GID + * is not a member of the 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 sync_interval; /* time between sync calls */ + 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 flush_interval;/* interval between runs of the + * delwri flush daemon. */ + xfs_sysctl_val_t age_buffer; /* time for buffer to age before + * we flush it. */ + xfs_sysctl_val_t io_bypass; /* toggle for directio io bypass */ +} 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_SYNC_INTERVAL = 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_FLUSH_INTERVAL = 16, + XFS_AGE_BUFFER = 17, + XFS_IO_BYPASS = 18, +}; + +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__ */ + diff --git a/sys/gnu/fs/xfs/FreeBSD/xfs_version.h b/sys/gnu/fs/xfs/FreeBSD/xfs_version.h new file mode 100644 index 0000000..96f9639 --- /dev/null +++ b/sys/gnu/fs/xfs/FreeBSD/xfs_version.h @@ -0,0 +1,44 @@ +/* + * 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__ */ diff --git a/sys/gnu/fs/xfs/FreeBSD/xfs_vfs.c b/sys/gnu/fs/xfs/FreeBSD/xfs_vfs.c new file mode 100644 index 0000000..a621e20 --- /dev/null +++ b/sys/gnu/fs/xfs/FreeBSD/xfs_vfs.c @@ -0,0 +1,372 @@ +/* + * 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_fs.h" +#include "xfs_macros.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 = (qaddr_t)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); +} diff --git a/sys/gnu/fs/xfs/FreeBSD/xfs_vfs.h b/sys/gnu/fs/xfs/FreeBSD/xfs_vfs.h new file mode 100644 index 0000000..c16ddcd --- /dev/null +++ b/sys/gnu/fs/xfs/FreeBSD/xfs_vfs.h @@ -0,0 +1,229 @@ +/* + * 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_UMOUNT 0x0008 /* unmount in progress */ +#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 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 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 */ +} 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__ */ diff --git a/sys/gnu/fs/xfs/FreeBSD/xfs_vnode.c b/sys/gnu/fs/xfs/FreeBSD/xfs_vnode.c new file mode 100644 index 0000000..ac85f87 --- /dev/null +++ b/sys/gnu/fs/xfs/FreeBSD/xfs_vnode.c @@ -0,0 +1,210 @@ +/* + * 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_macros.h" +#include "xfs_types.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_ialloc.h" +#include "xfs_attr_sf.h" +#include "xfs_dir_sf.h" +#include "xfs_dir2_sf.h" +#include "xfs_dinode.h" +#include "xfs_inode_item.h" +#include "xfs_inode.h" + +void +vn_init(void) +{ +} + +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, 0, curthread); + if (error) { + vdrop(vp); + return (NULL); + } + + vdrop(vp); + 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, + vmap_t *vmap) +{ + struct vnode *vp; + + vn_trace_entry(vp, "vn_purge", (inst_t *)__return_address); + + vp = vmap->v_vp; + + vn_lock(vp, LK_EXCLUSIVE, curthread); + vgone(vp); + VOP_UNLOCK(vp, 0, curthread); + vdrop(vp); +} + +/* + * Finish the removal of a vnode. + */ +void +vn_remove( + struct xfs_vnode *vp) +{ + vmap_t vmap; + + /* Make sure we don't do this to the same vnode twice */ + if (!(vp->v_fbhv)) + return; + + XFS_STATS_INC(vn_remove); + vn_trace_exit(vp, "vn_remove", (inst_t *)__return_address); + /* + * After the following purge the vnode + * will no longer exist. + */ + VMAP(vp, vmap); + vn_purge(vp, &vmap); +} + + +#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 */ diff --git a/sys/gnu/fs/xfs/FreeBSD/xfs_vnode.h b/sys/gnu/fs/xfs/FreeBSD/xfs_vnode.h new file mode 100644 index 0000000..d224cb8 --- /dev/null +++ b/sys/gnu/fs/xfs/FreeBSD/xfs_vnode.h @@ -0,0 +1,652 @@ +/* + * 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 xfs_ino_t vnumber_t; +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) */ + enum vtype v_type; /* vnode type */ + struct xfs_vfs *v_vfsp; /* ptr to containing VFS */ + vnumber_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; + +#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) + +#ifndef __FreeBSD__ +/* + * Convert between vnode types and inode formats (since POSIX.1 + * defines mode word of stat structure in terms of inode formats). + */ +extern enum vtype iftovt_tab[]; +extern u_short vttoif_tab[]; +#define IFTOVT(mode) (iftovt_tab[((mode) & S_IFMT) >> 12]) +#define VTTOIF(indx) (vttoif_tab[(int)(indx)]) +#define MAKEIMODE(indx, mode) (int)(VTTOIF(indx) | (mode)) +#endif + + +/* + * 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, unsigned int, unsigned long); +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 *, 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, mode, cr, rv) \ + rv = _VOP_(vop_access, vp)((vp)->v_fbhv, mode, 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 */ + +/* + * 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 */ + enum vtype va_type; /* vnode type (for create) */ + 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_type == VREG && ((mode) & (VSGID|(VEXEC>>3))) == VSGID) + +extern void vn_init(void); +extern int vn_wait(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; + +#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); \ + } + +extern void vn_purge(struct xfs_vnode *, vmap_t *); +extern xfs_vnode_t *vn_get(struct xfs_vnode *, vmap_t *); +extern int vn_revalidate(struct xfs_vnode *); +extern void vn_remove(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 */ + +/* + * 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 */ + +/* + * 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__ */ diff --git a/sys/gnu/fs/xfs/FreeBSD/xfs_vnops.c b/sys/gnu/fs/xfs/FreeBSD/xfs_vnops.c new file mode 100644 index 0000000..dc9f6f6 --- /dev/null +++ b/sys/gnu/fs/xfs/FreeBSD/xfs_vnops.c @@ -0,0 +1,1431 @@ +/* + * 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$ + */ +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/namei.h> +#include <sys/kernel.h> +#include <sys/fcntl.h> +#include <sys/mount.h> +#include <sys/unistd.h> +#include <sys/vnode.h> +#include <sys/dirent.h> +#include <sys/ioccom.h> +#include <sys/malloc.h> +#include <sys/extattr.h> + +#include <vm/vm.h> +#include <vm/vm_extern.h> +#include <vm/vm_object.h> +#include <vm/vm_page.h> +#include <vm/vm_pager.h> +#include <vm/vnode_pager.h> + +#include <fs/fifofs/fifo.h> + +#define NO_VFS_MACROS +#include "xfs.h" +#include "xfs_macros.h" +#include "xfs_types.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_ialloc.h" +#include "xfs_attr.h" +#include "xfs_attr_sf.h" +#include "xfs_dir_sf.h" +#include "xfs_dir2_sf.h" +#include "xfs_dinode.h" +#include "xfs_inode_item.h" +#include "xfs_inode.h" +#include "xfs_acl.h" +#include "xfs_cap.h" +#include "xfs_mac.h" +#include "xfs_iomap.h" +#include "xfs_clnt.h" +#include "xfs_mountops.h" + +/* + * Prototypes for XFS vnode operations. + */ +static vop_access_t _xfs_access; +static vop_advlock_t _xfs_advlock; +static vop_bmap_t _xfs_bmap; +static vop_cachedlookup_t _xfs_cachedlookup; +static vop_close_t _xfs_close; +static vop_create_t _xfs_create; +static vop_fsync_t _xfs_fsync; +static vop_getattr_t _xfs_getattr; +static vop_getextattr_t _xfs_getextattr; +static vop_inactive_t _xfs_inactive; +static vop_ioctl_t _xfs_ioctl; +static vop_link_t _xfs_link; +static vop_listextattr_t _xfs_listextattr; +static vop_mkdir_t _xfs_mkdir; +static vop_mknod_t _xfs_mknod; +static vop_open_t _xfs_open; +static vop_read_t _xfs_read; +static vop_readdir_t _xfs_readdir; +static vop_readlink_t _xfs_readlink; +static vop_reclaim_t _xfs_reclaim; +static vop_remove_t _xfs_remove; +static vop_rename_t _xfs_rename; +static vop_rmdir_t _xfs_rmdir; +static vop_setattr_t _xfs_setattr; +static vop_strategy_t _xfs_strategy; +static vop_symlink_t _xfs_symlink; +static vop_write_t _xfs_write; + +struct vop_vector xfs_vnops = { + .vop_default = &default_vnodeops, + .vop_access = _xfs_access, + .vop_advlock = _xfs_advlock, + .vop_bmap = _xfs_bmap, + .vop_cachedlookup = _xfs_cachedlookup, + .vop_close = _xfs_close, + .vop_create = _xfs_create, + .vop_fsync = _xfs_fsync, + .vop_getattr = _xfs_getattr, + .vop_getextattr = _xfs_getextattr, + .vop_inactive = _xfs_inactive, + .vop_ioctl = _xfs_ioctl, + .vop_link = _xfs_link, + .vop_listextattr = _xfs_listextattr, + .vop_lookup = vfs_cache_lookup, + .vop_mkdir = _xfs_mkdir, + .vop_mknod = _xfs_mknod, + .vop_open = _xfs_open, + .vop_read = _xfs_read, + .vop_readdir = _xfs_readdir, + .vop_readlink = _xfs_readlink, + .vop_reclaim = _xfs_reclaim, + .vop_remove = _xfs_remove, + .vop_rename = _xfs_rename, + .vop_rmdir = _xfs_rmdir, + .vop_setattr = _xfs_setattr, + .vop_strategy = _xfs_strategy, + .vop_symlink = _xfs_symlink, + .vop_write = _xfs_write, +}; + +/* + * FIFO's specific operations. + */ + +static vop_close_t _xfsfifo_close; +static vop_read_t _xfsfifo_read; +static vop_kqfilter_t _xfsfifo_kqfilter; +static vop_write_t _xfsfifo_write; + +struct vop_vector xfs_fifoops = { + .vop_default = &fifo_specops, + .vop_access = _xfs_access, + .vop_close = _xfsfifo_close, + .vop_fsync = _xfs_fsync, + .vop_getattr = _xfs_getattr, + .vop_inactive = _xfs_inactive, + .vop_kqfilter = _xfsfifo_kqfilter, + .vop_read = _xfsfifo_read, + .vop_reclaim = _xfs_reclaim, + .vop_setattr = _xfs_setattr, + .vop_write = _xfsfifo_write, +}; + +static int +_xfs_access( + struct vop_access_args /* { + struct vnode *a_vp; + int a_mode; + struct ucred *a_cred; + struct thread *a_td; + } */ *ap) +{ + int error; + + XVOP_ACCESS(VPTOXFSVP(ap->a_vp), ap->a_mode, ap->a_cred, error); + return (error); +} + +static int +_xfs_open( + struct vop_open_args /* { + struct vnode *a_vp; + int a_mode; + struct ucred *a_cred; + struct thread *a_td; + int a_fdidx; + } */ *ap) +{ + int error; + + XVOP_OPEN(VPTOXFSVP(ap->a_vp), ap->a_cred, error); + if (error == 0) + vnode_create_vobject(ap->a_vp, 0, ap->a_td); + return (error); +} + +static int +_xfs_close( + struct vop_close_args /* { + struct vnodeop_desc *a_desc; + struct vnode *a_vp; + int a_fflag; + struct ucred *a_cred; + struct thread *a_td; + } */ *ap) +{ + int error = 0; + /* XVOP_CLOSE(VPTOXFSVP(ap->a_vp), NULL, error); */ + return (error); +} + +static int +_xfs_getattr( + struct vop_getattr_args /* { + struct vnode *a_vp; + struct vattr *a_vap; + struct ucred *a_cred; + struct thread *a_td; + } */ *ap) +{ + struct vnode *vp = ap->a_vp; + struct vattr *vap = ap->a_vap; + struct mount *mp; + xfs_vattr_t va; + int error; + + + VATTR_NULL(vap); + memset(&va,0,sizeof(xfs_vattr_t)); + va.va_mask = XFS_AT_STAT|XFS_AT_GENCOUNT|XFS_AT_XFLAGS; + + XVOP_GETATTR(VPTOXFSVP(vp), &va, 0, ap->a_cred, error); + if (error) return (error); + + mp = vp->v_mount; + + vap->va_type = va.va_type; + vap->va_mode = va.va_mode; + vap->va_nlink = va.va_nlink; + vap->va_uid = va.va_uid; + vap->va_gid = va.va_gid; + vap->va_fsid = mp->mnt_stat.f_fsid.val[0]; + vap->va_fileid = va.va_nodeid; + vap->va_size = va.va_size; + vap->va_blocksize = va.va_blocksize; + vap->va_atime = va.va_atime; + vap->va_mtime = va.va_mtime; + vap->va_ctime = va.va_ctime; + vap->va_gen = va.va_gen; + vap->va_rdev = va.va_rdev; + vap->va_bytes = (va.va_nblocks << BBSHIFT); + + /* XFS now supports devices that have block sizes + * other than 512 so BBSHIFT will work for now + * but need to get this value from the super block + */ + + /* + * Fields with no direct equivalent in XFS + * leave initialized by VATTR_NULL + */ +#if 0 + vap->va_filerev = 0; + vap->va_birthtime = va.va_ctime; + vap->va_vaflags = 0; + vap->va_flags = 0; + vap->va_spare = 0; +#endif + + return (0); +} + +static int +_xfs_setattr( + struct vop_setattr_args /* { + struct vnode *a_vp; + struct vattr *a_vap; + struct ucred *a_cred; + struct thread *a_td; + } */ *ap) +{ + struct vnode *vp = ap->a_vp; + struct vattr *vap = ap->a_vap; + xfs_vattr_t va; + int error; + + /* + * Check for unsettable attributes. + */ + if ((vap->va_type != VNON) || (vap->va_nlink != VNOVAL) || + (vap->va_fsid != VNOVAL) || (vap->va_fileid != VNOVAL) || + (vap->va_blocksize != VNOVAL) || (vap->va_rdev != VNOVAL) || + ((int)vap->va_bytes != VNOVAL) || (vap->va_gen != VNOVAL)) + return (EINVAL); + + memset(&va, 0, sizeof(va)); + + if (vap->va_uid != (uid_t)VNOVAL) { + va.va_mask |= XFS_AT_UID; + va.va_uid = vap->va_uid; + } + if (vap->va_gid != (gid_t)VNOVAL) { + va.va_mask |= XFS_AT_GID; + va.va_gid = vap->va_gid; + } + if (vap->va_size != VNOVAL) { + va.va_mask |= XFS_AT_SIZE; + va.va_size = vap->va_size; + } + if (vap->va_atime.tv_sec != VNOVAL) { + va.va_mask |= XFS_AT_ATIME; + va.va_atime = vap->va_atime; + } + if (vap->va_mtime.tv_sec != VNOVAL) { + va.va_mask |= XFS_AT_MTIME; + va.va_mtime = vap->va_mtime; + } + if (vap->va_ctime.tv_sec != VNOVAL) { + va.va_mask |= XFS_AT_CTIME; + va.va_ctime = vap->va_ctime; + } + if (vap->va_mode != (mode_t)VNOVAL) { + va.va_mask |= XFS_AT_MODE; + va.va_mode = vap->va_mode; + } + + XVOP_SETATTR(VPTOXFSVP(vp), &va, 0, ap->a_cred, error); + return (error); +} + +static int +_xfs_inactive( + struct vop_inactive_args /* { + struct vnode *a_vp; + struct thread *a_td; + } */ *ap) +{ + struct vnode *vp = ap->a_vp; + struct thread *td = ap->a_td; + int error; + + XVOP_INACTIVE(VPTOXFSVP(vp), td->td_ucred, error); + return (error); +} + +static int +_xfs_read( + struct vop_read_args /* { + struct vnode *a_vp; + struct uio *a_uio; + int a_ioflag; + struct ucred *a_cred; + } */ *ap) +{ + struct vnode *vp = ap->a_vp; + struct uio *uio = ap->a_uio; + int error; + + switch (vp->v_type) { + case VREG: + break; + case VDIR: + return (EISDIR); + default: + return (EPERM); + }; + + XVOP_READ(VPTOXFSVP(vp), uio, ap->a_ioflag, ap->a_cred, error); + return error; +} + +int +xfs_read_file(xfs_mount_t *mp, xfs_inode_t *ip, struct uio *uio, int ioflag); + +int +xfs_read_file(xfs_mount_t *mp, xfs_inode_t *ip, struct uio *uio, int ioflag) +{ + xfs_fileoff_t lbn, nextlbn; + xfs_fsize_t bytesinfile; + long size, xfersize, blkoffset; + struct buf *bp; + struct vnode *vp; + int error, orig_resid; + int seqcount; + + seqcount = ioflag >> IO_SEQSHIFT; + + orig_resid = uio->uio_resid; + if (orig_resid <= 0) + return (0); + + vp = XFS_ITOV(ip)->v_vnode; + + /* + * Ok so we couldn't do it all in one vm trick... + * so cycle around trying smaller bites.. + */ + for (error = 0, bp = NULL; uio->uio_resid > 0; bp = NULL) { + if ((bytesinfile = ip->i_d.di_size - uio->uio_offset) <= 0) + break; + + lbn = XFS_B_TO_FSBT(mp, uio->uio_offset); + nextlbn = lbn + 1; + + /* + * size of buffer. The buffer representing the + * end of the file is rounded up to the size of + * the block type ( fragment or full block, + * depending ). + */ + size = mp->m_sb.sb_blocksize; + blkoffset = XFS_B_FSB_OFFSET(mp, uio->uio_offset); + + /* + * The amount we want to transfer in this iteration is + * one FS block less the amount of the data before + * our startpoint (duh!) + */ + xfersize = mp->m_sb.sb_blocksize - blkoffset; + + /* + * But if we actually want less than the block, + * or the file doesn't have a whole block more of data, + * then use the lesser number. + */ + if (uio->uio_resid < xfersize) + xfersize = uio->uio_resid; + if (bytesinfile < xfersize) + xfersize = bytesinfile; + + if (XFS_FSB_TO_B(mp, nextlbn) >= ip->i_d.di_size ) { + /* + * Don't do readahead if this is the end of the file. + */ + error = bread(vp, lbn, size, NOCRED, &bp); + } else if ((vp->v_mount->mnt_flag & MNT_NOCLUSTERR) == 0) { + /* + * Otherwise if we are allowed to cluster, + * grab as much as we can. + * + * XXX This may not be a win if we are not + * doing sequential access. + */ + error = cluster_read(vp, ip->i_d.di_size, lbn, + size, NOCRED, uio->uio_resid, seqcount, &bp); + } else if (seqcount > 1) { + /* + * If we are NOT allowed to cluster, then + * if we appear to be acting sequentially, + * fire off a request for a readahead + * as well as a read. Note that the 4th and 5th + * arguments point to arrays of the size specified in + * the 6th argument. + */ + int nextsize = mp->m_sb.sb_blocksize; + error = breadn(vp, lbn, + size, &nextlbn, &nextsize, 1, NOCRED, &bp); + } else { + /* + * Failing all of the above, just read what the + * user asked for. Interestingly, the same as + * the first option above. + */ + error = bread(vp, lbn, size, NOCRED, &bp); + } + if (error) { + brelse(bp); + bp = NULL; + break; + } + + /* + * If IO_DIRECT then set B_DIRECT for the buffer. This + * will cause us to attempt to release the buffer later on + * and will cause the buffer cache to attempt to free the + * underlying pages. + */ + if (ioflag & IO_DIRECT) + bp->b_flags |= B_DIRECT; + + /* + * We should only get non-zero b_resid when an I/O error + * has occurred, which should cause us to break above. + * However, if the short read did not cause an error, + * then we want to ensure that we do not uiomove bad + * or uninitialized data. + */ + size -= bp->b_resid; + if (size < xfersize) { + if (size == 0) + break; + xfersize = size; + } + + /* + * otherwise use the general form + */ + error = uiomove((char *)bp->b_data + blkoffset, + (int)xfersize, uio); + + if (error) + break; + + if (ioflag & (IO_VMIO|IO_DIRECT) ) { + /* + * If there are no dependencies, and it's VMIO, + * then we don't need the buf, mark it available + * for freeing. The VM has the data. + */ + bp->b_flags |= B_RELBUF; + brelse(bp); + } else { + /* + * Otherwise let whoever + * made the request take care of + * freeing it. We just queue + * it onto another list. + */ + bqrelse(bp); + } + } + + /* + * This can only happen in the case of an error + * because the loop above resets bp to NULL on each iteration + * and on normal completion has not set a new value into it. + * so it must have come from a 'break' statement + */ + if (bp != NULL) { + if (ioflag & (IO_VMIO|IO_DIRECT)) { + bp->b_flags |= B_RELBUF; + brelse(bp); + } else + bqrelse(bp); + } + + return (error); +} + +static int +_xfs_write(struct vop_write_args /* { + struct vnode *a_vp; + struct uio *a_uio; + int a_ioflag; + struct ucred *a_cred; + } */ *ap) +{ + struct vnode *vp = ap->a_vp; +/* struct uio *uio = ap->a_uio; */ + + if (vp->v_type != VREG) + return (EPERM); + return (EPERM); +} + +static int +_xfs_create( + struct vop_create_args /* { + struct vnode *a_dvp; + struct vnode **a_vpp; + struct componentname *a_cnp; + struct vattr *a_vap; + } */ *ap) +{ + struct vnode *dvp = ap->a_dvp; + struct vattr *vap = ap->a_vap; + struct thread *td = curthread; + struct ucred *credp = td->td_ucred; + struct componentname *cnp = ap->a_cnp; + xfs_vnode_t *xvp; + xfs_vattr_t va; + int error; + + memset(&va, 0, sizeof (va)); + va.va_mask |= XFS_AT_MODE; + va.va_mode = vap->va_mode; + va.va_mask |= XFS_AT_TYPE; + va.va_type = vap->va_type; + + xvp = NULL; + XVOP_CREATE(VPTOXFSVP(dvp), cnp, &va, &xvp, credp, error); + + if (error == 0) { + *ap->a_vpp = xvp->v_vnode; + VOP_LOCK(xvp->v_vnode, LK_EXCLUSIVE, td); + } + + return (error); +} + +static int +_xfs_remove( + struct vop_remove_args /* { + struct vnodeop_desc *a_desc; + struct vnode * a_dvp; + struct vnode * a_vp; + struct componentname * a_cnp; + } */ *ap) +{ + struct vnode *vp = ap->a_vp; + /* + struct vnode *dvp = ap->a_dvp; + struct componentname *cnp = ap->a_cnp; + */ + int error; + + if (vp->v_type == VDIR || vp->v_usecount != 1) + return (EPERM); + + error = 0; + cache_purge(vp); + return (error); +} + +static int +_xfs_rename( + struct vop_rename_args /* { + struct vnode *a_fdvp; + struct vnode *a_fvp; + struct componentname *a_fcnp; + struct vnode *a_tdvp; + struct vnode *a_tvp; + struct componentname *a_tcnp; + } */ *ap) +{ + struct vnode *fvp = ap->a_fvp; + struct vnode *tvp = ap->a_tvp; + struct vnode *fdvp = ap->a_fdvp; + struct vnode *tdvp = ap->a_tdvp; +/* struct componentname *tcnp = ap->a_tcnp; */ +/* struct componentname *fcnp = ap->a_fcnp;*/ + int error = EPERM; + + if (error) + goto out; + + /* Check for cross-device rename */ + if ((fvp->v_mount != tdvp->v_mount) || + (tvp && (fvp->v_mount != tvp->v_mount))) { + error = EXDEV; + goto out; + } + + if (tvp && tvp->v_usecount > 1) { + error = EBUSY; + goto out; + } + + if (fvp->v_type == VDIR) { + if (tvp != NULL && tvp->v_type == VDIR) + cache_purge(tdvp); + cache_purge(fdvp); + } +out: + if (tdvp == tvp) + vrele(tdvp); + else + vput(tdvp); + if (tvp) + vput(tvp); + vrele(fdvp); + vrele(fvp); + vgone(fvp); + if (tvp) + vgone(tvp); + return (error); +} + +static int +_xfs_link( + struct vop_link_args /* { + struct vnode *a_tdvp; + struct vnode *a_vp; + struct componentname *a_cnp; + } */ *ap) +{ + xfs_vnode_t *tdvp, *vp; + int error; + + tdvp = VPTOXFSVP(ap->a_tdvp); + vp = VPTOXFSVP(ap->a_vp); + XVOP_LINK(tdvp, vp, ap->a_cnp, NULL, error); + return (error); +} + +static int +_xfs_symlink( + struct vop_symlink_args /* { + struct vnode *a_dvp; + struct vnode **a_vpp; + struct componentname *a_cnp; + struct vattr *a_vap; + char *a_target; + } */ *ap) +{ + struct thread *td = curthread; + struct ucred *credp = td->td_ucred; + xfs_vnode_t *xvp; + xfs_vattr_t va; + int error; + + memset(&va, 0, sizeof (va)); + + va.va_mask |= XFS_AT_MODE; + va.va_mode = ap->a_vap->va_mode; + va.va_mask |= XFS_AT_TYPE; + va.va_type = ap->a_vap->va_type; + + XVOP_SYMLINK(VPTOXFSVP(ap->a_dvp), ap->a_cnp, &va, ap->a_target, + &xvp, credp, error); + + if (error == 0) { + *ap->a_vpp = xvp->v_vnode; + VOP_LOCK(xvp->v_vnode, LK_EXCLUSIVE, td); + } + + return (error); +} + +static int +_xfs_mknod( + struct vop_mknod_args /* { + struct vnode *a_dvp; + struct vnode **a_vpp; + struct componentname *a_cnp; + struct vattr *a_vap; + } */ *ap) +{ + struct vnode *dvp = ap->a_dvp; + struct vattr *vap = ap->a_vap; + struct thread *td = curthread; + struct ucred *credp = td->td_ucred; + struct componentname *cnp = ap->a_cnp; + xfs_vnode_t *xvp; + xfs_vattr_t va; + int error; + + memset(&va, 0, sizeof (va)); + va.va_mask |= XFS_AT_MODE; + va.va_mode = vap->va_mode; + va.va_mask |= XFS_AT_TYPE; + va.va_type = vap->va_type; + va.va_mask |= XFS_AT_RDEV; + va.va_rdev = vap->va_rdev; + + xvp = NULL; + XVOP_CREATE(VPTOXFSVP(dvp), cnp, &va, &xvp, credp, error); + + if (error == 0) { + *ap->a_vpp = xvp->v_vnode; + VOP_LOCK(xvp->v_vnode, LK_EXCLUSIVE, td); + } + + return (error); +} + +static int +_xfs_mkdir( + struct vop_mkdir_args /* { + struct vnode *a_dvp; + struct vnode **a_vpp; + struct componentname *a_cnp; + struct vattr *a_vap; + } */ *ap) +{ + struct vnode *dvp = ap->a_dvp; + struct vattr *vap = ap->a_vap; + struct thread *td = curthread; + struct ucred *credp = td->td_ucred; + struct componentname *cnp = ap->a_cnp; + xfs_vnode_t *xvp; + xfs_vattr_t va; + int error; + + memset(&va, 0, sizeof (va)); + va.va_mask |= XFS_AT_MODE; + va.va_mode = vap->va_mode; + va.va_mask |= XFS_AT_TYPE; + va.va_type = vap->va_type; + + xvp = NULL; + XVOP_MKDIR(VPTOXFSVP(dvp), cnp, &va, &xvp, credp, error); + + if (error == 0) { + *ap->a_vpp = xvp->v_vnode; + VOP_LOCK(xvp->v_vnode, LK_EXCLUSIVE, td); + } + + return (error); +} + +static int +_xfs_rmdir( + struct vop_rmdir_args /* { + struct vnode *a_dvp; + struct vnode *a_vp; + struct componentname *a_cnp; + } */ *ap) +{ + struct vnode *vp = ap->a_vp; + struct vnode *dvp = ap->a_dvp; +/* struct componentname *cnp = ap->a_cnp; */ + int error; + + if (dvp == vp) + return (EINVAL); + + error = EPERM; + + return (error); +} + +static int +_xfs_readdir( + struct vop_readdir_args /* { + struct vnode *a_vp; + struct uio *a_uio; + struct ucred *a_cred; + int *a_eofflag; + int *a_ncookies; + u_long **a_cookies; + } */ *ap) +{ + struct vnode *vp = ap->a_vp; + struct uio *uio = ap->a_uio; + int error; + off_t off; + int eof = 0; + + if (vp->v_type != VDIR) + return (EPERM); + if (ap->a_ncookies) { + return (EOPNOTSUPP); + } + + error = 0; + while (!eof){ + off = (int)uio->uio_offset; + + XVOP_READDIR(VPTOXFSVP(vp), uio, NULL, &eof, error); + if ((uio->uio_offset == off) || error) { + break; + } + } + + if (ap->a_eofflag) + *ap->a_eofflag = (eof != 0); + + return (error); +} + + +static int +_xfs_readlink( + struct vop_readlink_args /* { + struct vnode *a_vp; + struct uio *a_uio; + struct ucred *a_cred; + } */ *ap) +{ + struct vnode *vp = ap->a_vp; + struct uio *uio = ap->a_uio; + struct ucred *cred = ap->a_cred; + int error; + + XVOP_READLINK(VPTOXFSVP(vp), uio, 0, cred, error); + return (error); +} + +static int +_xfs_fsync( + struct vop_fsync_args /* { + struct vnode * a_vp; + int a_waitfor; + struct thread * a_td; + } */ *ap) +{ + xfs_vnode_t *vp = VPTOXFSVP(ap->a_vp); + int flags = FSYNC_DATA; + int error; + + if (ap->a_waitfor == MNT_WAIT) + flags |= FSYNC_WAIT; + XVOP_FSYNC(vp, flags, ap->a_td->td_ucred, (xfs_off_t)-1, (xfs_off_t)-1, + error); + + return (error); +} + +static int +_xfs_bmap( + struct vop_bmap_args /* { + struct vnode *a_vp; + daddr_t a_bn; + struct bufobj **a_bop; + daddr_t *a_bnp; + int *a_runp; + int *a_runb; + } */ *ap) +{ + xfs_iomap_t iomap; + xfs_off_t offset; + ssize_t size; + struct mount *mp; + struct xfs_mount *xmp; + struct xfs_vnode *xvp; + int error, maxrun, retbm; + + mp = ap->a_vp->v_mount; + xmp = XFS_VFSTOM(MNTTOVFS(mp)); + if (ap->a_bop != NULL) + *ap->a_bop = &xmp->m_ddev_targp->specvp->v_bufobj; + if (ap->a_bnp == NULL) + return (0); + + xvp = VPTOXFSVP(ap->a_vp); + retbm = 1; + + offset = XFS_FSB_TO_B(xmp, ap->a_bn); + size = XFS_FSB_TO_B(xmp, 1); + XVOP_BMAP(xvp, offset, size, BMAPI_READ, &iomap, &retbm, error); + if (error) + return (error); + if (retbm == 0 || iomap.iomap_bn == IOMAP_DADDR_NULL) { + *ap->a_bnp = (daddr_t)-1; + if (ap->a_runb) + *ap->a_runb = 0; + if (ap->a_runp) + *ap->a_runp = 0; + } else { + *ap->a_bnp = iomap.iomap_bn + btodb(iomap.iomap_delta); + maxrun = mp->mnt_iosize_max / mp->mnt_stat.f_iosize - 1; + if (ap->a_runb) { + *ap->a_runb = XFS_B_TO_FSB(xmp, iomap.iomap_delta); + if (*ap->a_runb > maxrun) + *ap->a_runb = maxrun; + } + if (ap->a_runp) { + *ap->a_runp = + XFS_B_TO_FSB(xmp, iomap.iomap_bsize + - iomap.iomap_delta - size); + if (*ap->a_runp > maxrun) + *ap->a_runp = maxrun; + } + } + return (0); +} + +static int +_xfs_strategy( + struct vop_strategy_args /* { + struct vnode *a_vp; + struct buf *a_bp; + } */ *ap) +{ + daddr_t blkno; + struct buf *bp;; + struct bufobj *bo; + struct vnode *vp; + struct xfs_mount *xmp; + int error; + + bp = ap->a_bp; + vp = ap->a_vp; + + KASSERT(ap->a_vp == ap->a_bp->b_vp, ("%s(%p != %p)", + __func__, ap->a_vp, ap->a_bp->b_vp)); + if (bp->b_blkno == bp->b_lblkno) { + error = VOP_BMAP(vp, bp->b_lblkno, NULL, &blkno, NULL, NULL); + bp->b_blkno = blkno; + bp->b_iooffset = (blkno << BBSHIFT); + if (error) { + bp->b_error = error; + bp->b_ioflags |= BIO_ERROR; + bufdone(bp); + return (error); + } + if ((long)bp->b_blkno == -1) + vfs_bio_clrbuf(bp); + } + if ((long)bp->b_blkno == -1) { + bufdone(bp); + return (0); + } + + xmp = XFS_VFSTOM(MNTTOVFS(vp->v_mount)); + bo = &xmp->m_ddev_targp->specvp->v_bufobj; + bo->bo_ops->bop_strategy(bo, bp); + return (0); +} + +int +_xfs_ioctl( + struct vop_ioctl_args /* { + struct vnode *a_vp; + u_long a_command; + caddr_t a_data; + int fflag; + struct ucred *cred; + struct thread *a_td; + } */ *ap) +{ +/* struct vnode *vp = ap->a_vp; */ +/* struct thread *p = ap->a_td; */ +/* struct file *fp; */ + int error; + + switch (ap->a_command) { + default: + error = EINVAL; + } + return (error); +} + +int +_xfs_advlock( + struct vop_advlock_args /* { + struct vnode *a_vp; + caddr_t a_id; + int a_op; + struct flock *a_fl; + int a_flags; + } */ *ap) +{ +/* struct vnode *vp = ap->a_vp;*/ + struct flock *fl = ap->a_fl; +/* caddr_t id = (caddr_t)1 */ /* ap->a_id */; +/* int flags = ap->a_flags; */ + off_t start, end, size; + int error/* , lkop */; + + /*KAN: temp */ + return (EOPNOTSUPP); + + size = 0; + error = 0; + switch (fl->l_whence) { + case SEEK_SET: + case SEEK_CUR: + start = fl->l_start; + break; + case SEEK_END: + start = fl->l_start + size; + default: + return (EINVAL); + } + if (start < 0) + return (EINVAL); + if (fl->l_len == 0) + end = -1; + else { + end = start + fl->l_len - 1; + if (end < start) + return (EINVAL); + } +#ifdef notyet + switch (ap->a_op) { + case F_SETLK: + error = lf_advlock(ap, &np->n_lockf, size); + break; + case F_UNLCK: + lf_advlock(ap, &np->n_lockf, size); + break; + case F_GETLK: + error = lf_advlock(ap, &np->n_lockf, size); + break; + default: + return (EINVAL); + } +#endif + return (error); +} + +static int +_xfs_cachedlookup( + struct vop_cachedlookup_args /* { + struct vnode * a_dvp; + struct vnode ** a_vpp; + struct componentname * a_cnp; + } */ *ap) +{ + struct vnode *dvp, *tvp; + struct xfs_vnode *cvp; + int islastcn; + int error; + struct vnode **vpp = ap->a_vpp; + struct componentname *cnp = ap->a_cnp; + struct ucred *cred = cnp->cn_cred; + int flags = cnp->cn_flags; + int nameiop = cnp->cn_nameiop; + struct thread *td = cnp->cn_thread; + + char *pname = cnp->cn_nameptr; + int namelen = cnp->cn_namelen; + + *vpp = NULL; + dvp = ap->a_dvp; + islastcn = flags & ISLASTCN; + + XVOP_LOOKUP(VPTOXFSVP(dvp), cnp, &cvp, 0, NULL, cred, error); + + if (error == ENOENT) { + if ((nameiop == CREATE || nameiop == RENAME || + nameiop == DELETE) && islastcn) + { + error = VOP_ACCESS(dvp, VWRITE, cred, td); + if (error) + return (error); + cnp->cn_flags |= SAVENAME; + return (EJUSTRETURN); + } + if ((cnp->cn_flags & MAKEENTRY) && nameiop != CREATE) + cache_enter(dvp, *vpp, cnp); + return (error); + } + if (error) + return (error); + + tvp = cvp->v_vnode; + + if (nameiop == DELETE && islastcn) { + if ((error = vn_lock(tvp, LK_EXCLUSIVE, td))) { + vrele(tvp); + goto err_out; + } + *vpp = tvp; + + /* Directory should be writable for deletes. */ + error = VOP_ACCESS(dvp, VWRITE, cred, td); + if (error) + goto err_out; + + /* XXXKAN: Permission checks for sticky dirs? */ + return (0); + } + + if (nameiop == RENAME && islastcn) { + if ((error = vn_lock(tvp, LK_EXCLUSIVE, td))) { + vrele(tvp); + goto err_out; + } + *vpp = tvp; + + if ((error = VOP_ACCESS(dvp, VWRITE, cred, td))) + goto err_out; + return (0); + } + + if (flags & ISDOTDOT) { + VOP_UNLOCK(dvp, 0, td); + error = vn_lock(tvp, cnp->cn_lkflags, td); + if (error) { + vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY, td); + vrele(tvp); + goto err_out; + } + *vpp = tvp; + } else if (namelen == 1 && pname[0] == '.') { + *vpp = tvp; + KASSERT(tvp == dvp, ("not same directory")); + } else { + if ((error = vn_lock(tvp, cnp->cn_lkflags, td))) { + vrele(tvp); + goto err_out; + } + *vpp = tvp; + } + + if (cnp->cn_flags & MAKEENTRY) + cache_enter(dvp, *vpp, cnp); + return (0); + +err_out: + if (*vpp != 0) + vput(*vpp); + return (error); +} + +static int +_xfs_reclaim( + struct vop_reclaim_args /* { + struct vnode *a_vp; + struct thread *a_td; + } */ *ap) +{ + + struct vnode *vp = ap->a_vp; + struct xfs_vnode *xfs_vp = VPTOXFSVP(vp); + int error; + + XVOP_RECLAIM(xfs_vp, error); + kmem_free(xfs_vp, sizeof(*xfs_vp)); + vp->v_data = NULL; + return (error); +} + +static int +_xfs_kqfilter( + struct vop_kqfilter_args /* { + struct vnodeop_desc *a_desc; + struct vnode *a_vp; + struct knote *a_kn; + } */ *ap) +{ + return (0); +} + +static __inline +struct xfs_inode * +xfs_vtoi(struct vnode *vp) +{ + if (VPTOXFSVP(vp) != 0) + return (XFS_BHVTOI(VPTOXFSVP(vp)->v_fbhv)); + return (NULL); +} + +/* + * Read wrapper for fifos. + */ +static int +_xfsfifo_read( + struct vop_read_args /* { + struct vnode *a_vp; + struct uio *a_uio; + int a_ioflag; + struct ucred *a_cred; + } */ *ap) +{ + int error, resid; + struct xfs_inode *ip; + struct uio *uio; + + uio = ap->a_uio; + resid = uio->uio_resid; + error = fifo_specops.vop_read(ap); + ip = xfs_vtoi(ap->a_vp); + if ((ap->a_vp->v_mount->mnt_flag & MNT_NOATIME) == 0 && ip != NULL && + (uio->uio_resid != resid || (error == 0 && resid != 0))) + xfs_ichgtime(ip, XFS_ICHGTIME_ACC); + return (error); +} + +/* + * Write wrapper for fifos. + */ +static int +_xfsfifo_write( + struct vop_write_args /* { + struct vnode *a_vp; + struct uio *a_uio; + int a_ioflag; + struct ucred *a_cred; + } */ *ap) +{ + int error, resid; + struct uio *uio; + struct xfs_inode *ip; + + uio = ap->a_uio; + resid = uio->uio_resid; + error = fifo_specops.vop_write(ap); + ip = xfs_vtoi(ap->a_vp); + if (ip != NULL && (uio->uio_resid != resid || + (error == 0 && resid != 0))) + xfs_ichgtime(ip, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG); + return (error); +} + +/* + * Close wrapper for fifos. + * + * Update the times on the inode then do device close. + */ +static int +_xfsfifo_close( + struct vop_close_args /* { + struct vnode *a_vp; + int a_fflag; + struct ucred *a_cred; + struct thread *a_td; + } */ *ap) +{ + + return (fifo_specops.vop_close(ap)); +} + +/* + * Kqfilter wrapper for fifos. + * + * Fall through to ufs kqfilter routines if needed + */ +static int +_xfsfifo_kqfilter( + struct vop_kqfilter_args /* { + struct vnodeop_desc *a_desc; + struct vnode *a_vp; + struct knote *a_kn; + } */ *ap) +{ + int error; + + error = fifo_specops.vop_kqfilter(ap); + if (error) + error = _xfs_kqfilter(ap); + return (error); +} + +static int +_xfs_getextattr( + struct vop_getextattr_args /* { + struct vnode *a_vp; + int a_attrnamespace; + const char *a_name; + struct uio *a_uio; + size_t *a_size; + struct ucred *a_cred; + struct thread *a_td; + } */ *ap) +{ + int error; + char *value; + int size; + + error = extattr_check_cred(ap->a_vp, ap->a_attrnamespace, + ap->a_cred, ap->a_td, VREAD); + if (error) + return (error); + + size = ATTR_MAX_VALUELEN; + value = (char *)kmem_zalloc(size, KM_SLEEP); + if (value == NULL) + return (ENOMEM); + + XVOP_ATTR_GET(VPTOXFSVP(ap->a_vp), ap->a_name, value, &size, 1, + ap->a_cred, error); + + if (ap->a_uio != NULL) { + if (ap->a_uio->uio_iov->iov_len < size) + error = ERANGE; + else + uiomove(value, size, ap->a_uio); + } + + if (ap->a_size != NULL) + *ap->a_size = size; + + kmem_free(value, ATTR_MAX_VALUELEN); + return (error); +} + +static int +_xfs_listextattr( + struct vop_listextattr_args /* { + struct vnode *a_vp; + int a_attrnamespace; + struct uio *a_uio; + size_t *a_size; + struct ucred *a_cred; + struct thread *a_td; + } */ *ap) +{ + int error; + char *buf = NULL; + int buf_len = 0; + attrlist_cursor_kern_t cursor = { 0 }; + int i; + char name_len; + int attrnames_len = 0; + int xfs_flags = ATTR_KERNAMELS; + + error = extattr_check_cred(ap->a_vp, ap->a_attrnamespace, + ap->a_cred, ap->a_td, VREAD); + if (error) + return (error); + + if (ap->a_attrnamespace & EXTATTR_NAMESPACE_USER) + xfs_flags |= ATTR_KERNORMALS; + + if (ap->a_attrnamespace & EXTATTR_NAMESPACE_SYSTEM) + xfs_flags |= ATTR_KERNROOTLS; + + if (ap->a_uio == NULL || ap->a_uio->uio_iov[0].iov_base == NULL) { + xfs_flags |= ATTR_KERNOVAL; + buf_len = 0; + } else { + buf = ap->a_uio->uio_iov[0].iov_base; + buf_len = ap->a_uio->uio_iov[0].iov_len; + } + + XVOP_ATTR_LIST(VPTOXFSVP(ap->a_vp), buf, buf_len, xfs_flags, + &cursor, ap->a_cred, error); + if (error < 0) { + attrnames_len = -error; + error = 0; + } + if (buf == NULL) + goto done; + + /* + * extattr_list expects a list of names. Each list + * entry consists of one byte for the name length, followed + * by the name (not null terminated) + */ + name_len=0; + for(i=attrnames_len-1; i > 0 ; --i) { + buf[i] = buf[i-1]; + if (buf[i]) + ++name_len; + else { + buf[i] = name_len; + name_len = 0; + } + } + buf[0] = name_len; + + if (ap->a_uio != NULL) + ap->a_uio->uio_resid -= attrnames_len; + +done: + if (ap->a_size != NULL) + *ap->a_size = attrnames_len; + + return (error); +} diff --git a/sys/gnu/fs/xfs/FreeBSD/xfsdmapistubs.c b/sys/gnu/fs/xfs/FreeBSD/xfsdmapistubs.c new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/sys/gnu/fs/xfs/FreeBSD/xfsdmapistubs.c diff --git a/sys/gnu/fs/xfs/FreeBSD/xfsquotasstubs.c b/sys/gnu/fs/xfs/FreeBSD/xfsquotasstubs.c new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/sys/gnu/fs/xfs/FreeBSD/xfsquotasstubs.c diff --git a/sys/gnu/fs/xfs/FreeBSD/xfsrtstubs.c b/sys/gnu/fs/xfs/FreeBSD/xfsrtstubs.c new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/sys/gnu/fs/xfs/FreeBSD/xfsrtstubs.c |