Commit 9589ef2a authored by Nathan Scott's avatar Nathan Scott

[XFS] Next step in bhv code cleanup - this is a start on moving quota and dmapi

into behavior layers, purging several points where these sit slap bang in
the middle of XFS code (esp. read_super).  Also removes numerous #ifdef's
and a bunch of unused #define's from all over the place.  More to come.

SGI Modid: 2.5.x-xfs:slinx:141499a
parent d189d057
#
# Copyright (c) 2000-2002 Silicon Graphics, Inc. All Rights Reserved.
# 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
......@@ -32,10 +32,6 @@
# Makefile for XFS on Linux.
#
# This needs -I. because everything does #include <xfs.h> instead of "xfs.h".
# The code is wrong, local files should be included using "xfs.h", not <xfs.h>
# but I am not going to change every file at the moment.
EXTRA_CFLAGS += -Ifs/xfs -funsigned-char
ifeq ($(CONFIG_XFS_DEBUG),y)
......@@ -54,6 +50,7 @@ xfs-$(CONFIG_XFS_QUOTA) += xfs_dquot.o \
xfs_dquot_item.o \
xfs_trans_dquot.o \
xfs_qm_syscalls.o \
xfs_qmops.o \
xfs_qm.o
xfs-$(CONFIG_XFS_POSIX_ACL) += xfs_acl.o
......@@ -127,6 +124,7 @@ xfs-y += $(addprefix linux/, \
xfs_iops.o \
xfs_lrw.o \
xfs_super.o \
xfs_vfs.o \
xfs_vnode.o)
# Objects in support/
......
/*
* Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved.
* 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
......@@ -30,41 +30,77 @@
* http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
*
*/
#include <xfs.h>
/*
* Source file used to associate/disassociate behaviors with virtualized
* objects. See behavior.h for more information about behaviors, etc.
* objects. See xfs_behavior.h for more information about behaviors, etc.
*
* The implementation is split between functions in this file and macros
* in behavior.h.
* in xfs_behavior.h.
*/
#include <xfs.h>
kmem_zone_t *bhv_global_zone;
/*
* Global initialization function called out of main.
* Insert a new behavior descriptor into a behavior chain.
*
* The behavior chain is ordered based on the 'position' number which
* lives in the first field of the ops vector (higher numbers first).
*
* Attemps to insert duplicate ops result in an EINVAL return code.
* Otherwise, return 0 to indicate success.
*/
void
bhv_global_init(void)
int
bhv_insert(bhv_head_t *bhp, bhv_desc_t *bdp)
{
bhv_desc_t *curdesc, *prev;
int position;
/*
* Validate the position value of the new behavior.
*/
position = BHV_POSITION(bdp);
ASSERT(position >= BHV_POSITION_BASE && position <= BHV_POSITION_TOP);
/*
* Initialize a behavior zone used by subsystems using behaviors
* but without any private data. In the UNIKERNEL case, this zone
* is used only for behaviors that are not yet isolated to a single
* cell. The only such user is in pshm.c in which a dummy vnode is
* obtained in support of vce avoidance logic.
* Find location to insert behavior. Check for duplicates.
*/
bhv_global_zone = kmem_zone_init(sizeof(bhv_desc_t), "bhv_global_zone");
prev = NULL;
for (curdesc = bhp->bh_first;
curdesc != NULL;
curdesc = curdesc->bd_next) {
/* Check for duplication. */
if (curdesc->bd_ops == bdp->bd_ops) {
ASSERT(0);
return EINVAL;
}
/* Find correct position */
if (position >= BHV_POSITION(curdesc)) {
ASSERT(position != BHV_POSITION(curdesc));
break; /* found it */
}
prev = curdesc;
}
if (prev == NULL) {
/* insert at front of chain */
bdp->bd_next = bhp->bh_first;
bhp->bh_first = bdp;
} else {
/* insert after prev */
bdp->bd_next = prev->bd_next;
prev->bd_next = bdp;
}
return 0;
}
/*
* Remove a behavior descriptor from a position in a behavior chain;
* the postition is guaranteed not to be the first position.
* Should only be called by the bhv_remove() macro.
*
* The act of modifying the chain is done atomically w.r.t. ops-in-progress
* (see comment at top of behavior.h for more info on synchronization).
*/
void
bhv_remove_not_first(bhv_head_t *bhp, bhv_desc_t *bdp)
......@@ -86,7 +122,6 @@ bhv_remove_not_first(bhv_head_t *bhp, bhv_desc_t *bdp)
ASSERT(curdesc == bdp);
prev->bd_next = bdp->bd_next; /* remove from after prev */
/* atomic wrt oip's */
}
/*
......@@ -110,20 +145,28 @@ bhv_lookup(bhv_head_t *bhp, void *ops)
}
/*
* Look for a specific ops vector on the specified behavior chain.
* Return the associated behavior descriptor. Or NULL, if not found.
*
* The caller has not read locked the behavior chain, so acquire the
* lock before traversing the chain.
* Looks for the first behavior within a specified range of positions.
* Return the associated behavior descriptor. Or NULL, if none found.
*/
bhv_desc_t *
bhv_lookup_unlocked(bhv_head_t *bhp, void *ops)
bhv_lookup_range(bhv_head_t *bhp, int low, int high)
{
bhv_desc_t *bdp;
bhv_desc_t *curdesc;
for (curdesc = bhp->bh_first;
curdesc != NULL;
curdesc = curdesc->bd_next) {
bdp = bhv_lookup(bhp, ops);
int position = BHV_POSITION(curdesc);
return bdp;
if (position <= high) {
if (position >= low)
return curdesc;
return NULL;
}
}
return NULL;
}
/*
......@@ -134,49 +177,36 @@ bhv_lookup_unlocked(bhv_head_t *bhp, void *ops)
* lock before traversing the chain.
*/
bhv_desc_t *
bhv_base_unlocked(bhv_head_t *bhp)
bhv_base(bhv_head_t *bhp)
{
bhv_desc_t *curdesc;
for (curdesc = bhp->bh_first;
curdesc != NULL;
curdesc = curdesc->bd_next) {
if (curdesc->bd_next == NULL)
if (curdesc->bd_next == NULL) {
return curdesc;
}
}
return NULL;
}
#define BHVMAGIC (void *)0xf00d
/* ARGSUSED */
void
bhv_head_init(
bhv_head_t *bhp,
char *name)
{
bhp->bh_first = NULL;
bhp->bh_lockp = BHVMAGIC;
}
/* ARGSUSED */
void
bhv_head_reinit(
bhv_head_t *bhp)
{
ASSERT(bhp->bh_first == NULL);
ASSERT(bhp->bh_lockp == BHVMAGIC);
}
void
bhv_insert_initial(
bhv_head_t *bhp,
bhv_desc_t *bdp)
{
ASSERT(bhp->bh_first == NULL);
ASSERT(bhp->bh_lockp == BHVMAGIC);
(bhp)->bh_first = bdp;
}
......@@ -185,7 +215,4 @@ bhv_head_destroy(
bhv_head_t *bhp)
{
ASSERT(bhp->bh_first == NULL);
ASSERT(bhp->bh_lockp == BHVMAGIC);
bhp->bh_lockp = NULL;
}
/*
* Copyright (c) 2000, 2002 Silicon Graphics, Inc. All Rights Reserved.
* 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
......@@ -92,7 +92,7 @@
*
*/
typedef void bhv_head_lock_t;
struct bhv_head_lock;
/*
* Behavior head. Head of the chain of behaviors.
......@@ -100,7 +100,7 @@ typedef void bhv_head_lock_t;
*/
typedef struct bhv_head {
struct bhv_desc *bh_first; /* first behavior in chain */
bhv_head_lock_t *bh_lockp; /* pointer to lock info struct */
struct bhv_head_lock *bh_lockp; /* pointer to lock info struct */
} bhv_head_t;
/*
......@@ -128,10 +128,8 @@ typedef struct bhv_identity {
typedef bhv_identity_t bhv_position_t;
#define BHV_IDENTITY_INIT(id,pos) {id, pos}
#define BHV_IDENTITY_INIT_POSITION(pos) BHV_IDENTITY_INIT(0, pos)
/*
* Define boundaries of position values.
*/
......@@ -154,7 +152,7 @@ typedef bhv_identity_t bhv_position_t;
extern void bhv_head_init(bhv_head_t *, char *);
extern void bhv_head_destroy(bhv_head_t *);
extern void bhv_head_reinit(bhv_head_t *);
extern int bhv_insert(bhv_head_t *, bhv_desc_t *);
extern void bhv_insert_initial(bhv_head_t *, bhv_desc_t *);
/*
......@@ -196,7 +194,11 @@ extern void bhv_insert_initial(bhv_head_t *, bhv_desc_t *);
*/
extern void bhv_remove_not_first(bhv_head_t *bhp, bhv_desc_t *bdp);
extern bhv_desc_t * bhv_lookup(bhv_head_t *bhp, void *ops);
extern bhv_desc_t * bhv_lookup_unlocked(bhv_head_t *bhp, void *ops);
extern bhv_desc_t * bhv_base_unlocked(bhv_head_t *bhp);
extern bhv_desc_t * bhv_lookup_range(bhv_head_t *bhp, int low, int high);
extern bhv_desc_t * bhv_base(bhv_head_t *bhp);
/* No bhv locking on Linux */
#define bhv_lookup_unlocked bhv_lookup
#define bhv_base_unlocked bhv_base
#endif /* __XFS_BEHAVIOR_H__ */
/*
* Copyright (c) 2000-2002 Silicon Graphics, Inc. All Rights Reserved.
* 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
......@@ -130,7 +130,7 @@ xfs_find_handle(
int lock_mode;
/* need to get access to the xfs_inode to read the generation */
bhv = VNODE_TO_FIRST_BHV(vp);
bhv = vn_bhv_lookup_unlocked(VN_BHV_HEAD(vp), &xfs_vnodeops);
ASSERT(bhv);
ip = XFS_BHVTOI(bhv);
ASSERT(ip);
......
/*
* Copyright (c) 2000-2002 Silicon Graphics, Inc. All Rights Reserved.
* 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
......@@ -44,6 +44,7 @@
#include <linux/major.h>
#include <linux/pagemap.h>
#include <linux/vfs.h>
#include <linux/seq_file.h>
#include <asm/page.h>
#include <asm/div64.h>
......@@ -160,6 +161,15 @@ static inline void set_buffer_unwritten_io(struct buffer_head *bh)
#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 */
......
/*
* Copyright (c) 2000-2002 Silicon Graphics, Inc. All Rights Reserved.
* 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
......@@ -31,54 +31,13 @@
*/
#include <xfs.h>
#include <linux/bitops.h>
#include <linux/blkdev.h>
#include <linux/namei.h>
#include <linux/pagemap.h>
#include <linux/major.h>
#include <linux/init.h>
#include <linux/ctype.h>
#include <linux/seq_file.h>
#include <linux/mount.h>
#include "xfs_version.h"
/* xfs_vfs[ops].c */
extern int xfs_init(void);
extern void xfs_cleanup(void);
/* For kernels which have the s_maxbytes field - set it */
#ifdef MAX_NON_LFS
# define set_max_bytes(sb) ((sb)->s_maxbytes = XFS_MAX_FILE_OFFSET)
#else
# define set_max_bytes(sb) do { } while (0)
#endif
#ifdef CONFIG_XFS_POSIX_ACL
# define set_posix_acl(sb) ((sb)->s_flags |= MS_POSIXACL)
#else
# define set_posix_acl(sb) do { } while (0)
#endif
#ifdef CONFIG_XFS_QUOTA
STATIC struct quotactl_ops linvfs_qops = {
.get_xstate = linvfs_getxstate,
.set_xstate = linvfs_setxstate,
.get_xquota = linvfs_getxquota,
.set_xquota = linvfs_setxquota,
};
# define set_quota_ops(sb) ((sb)->s_qcop = &linvfs_qops)
#else
# define set_quota_ops(sb) do { } while (0)
#endif
#ifdef CONFIG_XFS_DMAPI
int dmapi_init(void);
void dmapi_uninit(void);
#else
#define dmapi_init()
#define dmapi_uninit()
#endif
STATIC struct quotactl_ops linvfs_qops;
STATIC struct super_operations linvfs_sops;
STATIC struct export_operations linvfs_export_ops;
......@@ -86,52 +45,53 @@ STATIC struct export_operations linvfs_export_ops;
#define MNTOPT_LOGBSIZE "logbsize" /* size of XFS log buffers */
#define MNTOPT_LOGDEV "logdev" /* log device */
#define MNTOPT_RTDEV "rtdev" /* realtime I/O device */
#define MNTOPT_DMAPI "dmapi" /* DMI enabled (DMAPI / XDSM) */
#define MNTOPT_XDSM "xdsm" /* DMI enabled (DMAPI / XDSM) */
#define MNTOPT_BIOSIZE "biosize" /* log2 of preferred buffered io size */
#define MNTOPT_WSYNC "wsync" /* safe-mode nfs compatible mount */
#define MNTOPT_INO64 "ino64" /* force inodes into 64-bit range */
#define MNTOPT_NOALIGN "noalign" /* turn off stripe alignment */
#define MNTOPT_SUNIT "sunit" /* data volume stripe unit */
#define MNTOPT_SWIDTH "swidth" /* data volume stripe width */
#define MNTOPT_NOUUID "nouuid" /* ignore filesystem UUID */
#define MNTOPT_MTPT "mtpt" /* filesystem mount point */
#define MNTOPT_NORECOVERY "norecovery" /* don't run XFS recovery */
#define MNTOPT_NOLOGFLUSH "nologflush" /* don't hard flush on log writes */
#define MNTOPT_OSYNCISOSYNC "osyncisosync" /* o_sync is REALLY o_sync */
#define MNTOPT_QUOTA "quota" /* disk quotas */
#define MNTOPT_NOQUOTA "noquota" /* no quotas */
#define MNTOPT_UQUOTA "usrquota" /* user quota enabled */
#define MNTOPT_GQUOTA "grpquota" /* group quota enabled */
#define MNTOPT_UQUOTANOENF "uqnoenforce"/* user quota limit enforcement */
#define MNTOPT_GQUOTANOENF "gqnoenforce"/* group quota limit enforcement */
#define MNTOPT_QUOTANOENF "qnoenforce" /* same as uqnoenforce */
#define MNTOPT_NOUUID "nouuid" /* Ignore FS uuid */
#define MNTOPT_NOLOGFLUSH "nologflush" /* Don't use hard flushes in
log writing */
#define MNTOPT_MTPT "mtpt" /* filesystem mount point */
STATIC int
STATIC struct xfs_mount_args *
args_allocate(
struct super_block *sb)
{
struct xfs_mount_args *args;
args = kmem_zalloc(sizeof(struct xfs_mount_args), KM_SLEEP);
args->logbufs = args->logbufsize = -1;
strncpy(args->fsname, sb->s_id, MAXNAMELEN);
/* Copy the already-parsed mount(2) flags we're interested in */
if (sb->s_flags & MS_NOATIME)
args->flags |= XFSMNT_NOATIME;
/* Default to 32 bit inodes on Linux all the time */
args->flags |= XFSMNT_32BITINODES;
return args;
}
int
xfs_parseargs(
struct bhv_desc *bhv,
char *options,
int flags,
struct xfs_mount_args *args)
struct xfs_mount_args *args,
int update)
{
struct vfs *vfsp = bhvtovfs(bhv);
char *this_char, *value, *eov;
int dsunit, dswidth, vol_dsunit, vol_dswidth;
int logbufs, logbufsize;
int iosize;
/* Default to 32 bit inodes on linux all the time */
args->flags |= XFSMNT_32BITINODES;
/* Copy the already-parsed mount(2) flags we're interested in */
if (flags & MS_NOATIME)
args->flags |= XFSMNT_NOATIME;
if (!options) {
args->logbufs = args->logbufsize = -1;
if (!options)
return 0;
}
logbufs = logbufsize = -1;
iosize = dsunit = dswidth = vol_dsunit = vol_dswidth = 0;
while ((this_char = strsep(&options, ",")) != NULL) {
......@@ -146,22 +106,23 @@ xfs_parseargs(
MNTOPT_LOGBUFS);
return -EINVAL;
}
logbufs = simple_strtoul(value, &eov, 10);
args->logbufs = simple_strtoul(value, &eov, 10);
} else if (!strcmp(this_char, MNTOPT_LOGBSIZE)) {
int in_kilobytes = 0;
int last, in_kilobytes = 0;
if (!value || !*value) {
printk("XFS: %s option requires an argument\n",
MNTOPT_LOGBSIZE);
return -EINVAL;
}
if (toupper(value[strlen(value)-1]) == 'K') {
last = strlen(value) - 1;
if (value[last] == 'K' || value[last] == 'k') {
in_kilobytes = 1;
value[strlen(value)-1] = '\0';
value[last] = '\0';
}
logbufsize = simple_strtoul(value, &eov, 10);
args->logbufsize = simple_strtoul(value, &eov, 10);
if (in_kilobytes)
logbufsize = logbufsize * 1024;
args->logbufsize <<= 10;
} else if (!strcmp(this_char, MNTOPT_LOGDEV)) {
if (!value || !*value) {
printk("XFS: %s option requires an argument\n",
......@@ -176,17 +137,6 @@ xfs_parseargs(
return -EINVAL;
}
strncpy(args->mtpt, value, MAXNAMELEN);
#if CONFIG_XFS_DMAPI
} else if (!strcmp(this_char, MNTOPT_DMAPI)) {
args->flags |= XFSMNT_DMAPI;
} else if (!strcmp(this_char, MNTOPT_XDSM)) {
args->flags |= XFSMNT_DMAPI;
#else
} else if (!strcmp(this_char, MNTOPT_DMAPI) ||
!strcmp(this_char, MNTOPT_XDSM)) {
printk("XFS: this kernel does not support dmapi/xdsm.\n");
return -EINVAL;
#endif
} else if (!strcmp(this_char, MNTOPT_RTDEV)) {
if (!value || !*value) {
printk("XFS: %s option requires an argument\n",
......@@ -210,28 +160,12 @@ xfs_parseargs(
} else if (!strcmp(this_char, MNTOPT_NORECOVERY)) {
args->flags |= XFSMNT_NORECOVERY;
} else if (!strcmp(this_char, MNTOPT_INO64)) {
#ifdef XFS_BIG_FILESYSTEMS
args->flags |= XFSMNT_INO64;
#else
#ifndef XFS_BIG_FILESYSTEMS
printk("XFS: %s option not allowed on this system\n",
MNTOPT_INO64);
return -EINVAL;
#endif
} else if (!strcmp(this_char, MNTOPT_UQUOTA)) {
args->flags |= XFSMNT_UQUOTA | XFSMNT_UQUOTAENF;
} else if (!strcmp(this_char, MNTOPT_QUOTA)) {
args->flags |= XFSMNT_UQUOTA | XFSMNT_UQUOTAENF;
} else if (!strcmp(this_char, MNTOPT_UQUOTANOENF)) {
args->flags |= XFSMNT_UQUOTA;
args->flags &= ~XFSMNT_UQUOTAENF;
} else if (!strcmp(this_char, MNTOPT_QUOTANOENF)) {
args->flags |= XFSMNT_UQUOTA;
args->flags &= ~XFSMNT_UQUOTAENF;
} else if (!strcmp(this_char, MNTOPT_GQUOTA)) {
args->flags |= XFSMNT_GQUOTA | XFSMNT_GQUOTAENF;
} else if (!strcmp(this_char, MNTOPT_GQUOTANOENF)) {
args->flags |= XFSMNT_GQUOTA;
args->flags &= ~XFSMNT_GQUOTAENF;
} else if (!strcmp(this_char, MNTOPT_NOALIGN)) {
args->flags |= XFSMNT_NOALIGN;
} else if (!strcmp(this_char, MNTOPT_SUNIT)) {
......@@ -264,7 +198,7 @@ printk("XFS: irixsgid is now a sysctl(2) variable, option is deprecated.\n");
}
if (args->flags & XFSMNT_NORECOVERY) {
if ((flags & MS_RDONLY) == 0) {
if ((vfsp->vfs_flag & VFS_RDONLY) == 0) {
printk("XFS: no-recovery mounts must be read-only.\n");
return -EINVAL;
}
......@@ -292,22 +226,21 @@ printk("XFS: irixsgid is now a sysctl(2) variable, option is deprecated.\n");
if (dsunit) {
args->sunit = dsunit;
args->flags |= XFSMNT_RETERR;
} else
} else {
args->sunit = vol_dsunit;
}
dswidth ? (args->swidth = dswidth) :
(args->swidth = vol_dswidth);
} else
} else {
args->sunit = args->swidth = 0;
args->logbufs = logbufs;
args->logbufsize = logbufsize;
}
return 0;
}
STATIC int
int
xfs_showargs(
struct vfs *vfsp,
struct bhv_desc *bhv,
struct seq_file *m)
{
static struct proc_xfs_info {
......@@ -322,7 +255,7 @@ xfs_showargs(
{ 0, NULL }
};
struct proc_xfs_info *xfs_infop;
struct xfs_mount *mp = XFS_BHVTOM(vfsp->vfs_fbhv);
struct xfs_mount *mp = XFS_BHVTOM(bhv);
char b[BDEVNAME_SIZE];
for (xfs_infop = xfs_info; xfs_infop->flag; xfs_infop++) {
......@@ -330,18 +263,6 @@ xfs_showargs(
seq_puts(m, xfs_infop->str);
}
if (mp->m_qflags & XFS_UQUOTA_ACCT) {
(mp->m_qflags & XFS_UQUOTA_ENFD) ?
seq_puts(m, "," MNTOPT_UQUOTA) :
seq_puts(m, "," MNTOPT_UQUOTANOENF);
}
if (mp->m_qflags & XFS_GQUOTA_ACCT) {
(mp->m_qflags & XFS_GQUOTA_ENFD) ?
seq_puts(m, "," MNTOPT_GQUOTA) :
seq_puts(m, "," MNTOPT_GQUOTANOENF);
}
if (mp->m_flags & XFS_MOUNT_DFLT_IOSIZE)
seq_printf(m, "," MNTOPT_BIOSIZE "=%d", mp->m_writeio_log);
......@@ -368,9 +289,6 @@ xfs_showargs(
seq_printf(m, "," MNTOPT_SWIDTH "=%d",
(int)XFS_FSB_TO_BB(mp, mp->m_swidth));
if (vfsp->vfs_flag & VFS_DMI)
seq_puts(m, "," MNTOPT_DMAPI);
return 0;
}
......@@ -443,15 +361,15 @@ xfs_initialize_vnode(
xfs_inode_t *ip = XFS_BHVTOI(inode_bhv);
struct inode *inode = LINVFS_GET_IP(vp);
if (vp->v_fbhv == NULL) {
if (inode_bhv->bd_vobj == NULL) {
vp->v_vfsp = bhvtovfs(bdp);
bhv_desc_init(&(ip->i_bhv_desc), ip, vp, &xfs_vnodeops);
bhv_insert_initial(VN_BHV_HEAD(vp), &(ip->i_bhv_desc));
bhv_desc_init(inode_bhv, ip, vp, &xfs_vnodeops);
bhv_insert(VN_BHV_HEAD(vp), inode_bhv);
}
vp->v_type = IFTOVT(ip->i_d.di_mode);
/* Have we been called during the new inode create process,
* in which case we are too early to fill in the linux inode.
* in which case we are too early to fill in the Linux inode.
*/
if (vp->v_type == VNON)
return;
......@@ -497,7 +415,7 @@ xfs_free_buftarg(
xfs_buftarg_t *btp)
{
pagebuf_delwri_flush(btp, PBDF_WAIT, NULL);
kfree(btp);
kmem_free(btp, sizeof(*btp));
}
void
......@@ -606,119 +524,7 @@ STATIC void
destroy_inodecache( void )
{
if (kmem_cache_destroy(linvfs_inode_cachep))
printk(KERN_INFO
"linvfs_inode_cache: not all structures were freed\n");
}
static int
linvfs_fill_super(
struct super_block *sb,
void *data,
int silent)
{
vfs_t *vfsp;
vfsops_t *vfsops;
vnode_t *rootvp;
struct inode *ip;
struct xfs_mount_args *args;
struct statfs statvfs;
int error = EINVAL;
args = kmalloc(sizeof(struct xfs_mount_args), GFP_KERNEL);
if (!args)
return -EINVAL;
memset(args, 0, sizeof(struct xfs_mount_args));
args->slcount = args->stimeout = args->ctimeout = -1;
strncpy(args->fsname, sb->s_id, MAXNAMELEN);
if (xfs_parseargs((char *)data, sb->s_flags, args))
goto out_null;
/* Kludge in XFS until we have other VFS/VNODE FSs */
vfsops = &xfs_vfsops;
/* Set up the vfs_t structure */
vfsp = vfs_allocate();
if (!vfsp) {
error = ENOMEM;
goto out_null;
}
if (sb->s_flags & MS_RDONLY)
vfsp->vfs_flag |= VFS_RDONLY;
vfsp->vfs_super = sb;
set_max_bytes(sb);
set_quota_ops(sb);
sb->s_op = &linvfs_sops;
sb->s_export_op = &linvfs_export_ops;
sb_min_blocksize(sb, BBSIZE);
LINVFS_SET_VFS(sb, vfsp);
VFSOPS_MOUNT(vfsops, vfsp, args, NULL, error);
if (error)
goto fail_vfsop;
VFS_STATVFS(vfsp, &statvfs, NULL, error);
if (error)
goto fail_unmount;
sb->s_magic = XFS_SB_MAGIC;
sb->s_dirt = 1;
sb->s_blocksize = statvfs.f_bsize;
sb->s_blocksize_bits = ffs(statvfs.f_bsize) - 1;
set_posix_acl(sb);
VFS_ROOT(vfsp, &rootvp, error);
if (error)
goto fail_unmount;
ip = LINVFS_GET_IP(rootvp);
sb->s_root = d_alloc_root(ip);
if (!sb->s_root)
goto fail_vnrele;
if (is_bad_inode(sb->s_root->d_inode))
goto fail_vnrele;
/* Don't set the VFS_DMI flag until here because we don't want
* to send events while replaying the log.
*/
if (args->flags & XFSMNT_DMAPI) {
vfsp->vfs_flag |= VFS_DMI;
VFSOPS_DMAPI_MOUNT(vfsops, vfsp, args->mtpt, args->fsname,
error);
if (error) {
if (atomic_read(&sb->s_active) == 1)
vfsp->vfs_flag &= ~VFS_DMI;
goto fail_vnrele;
}
}
vn_trace_exit(rootvp, __FUNCTION__, (inst_t *)__return_address);
kfree(args);
return 0;
fail_vnrele:
if (sb->s_root) {
dput(sb->s_root);
sb->s_root = NULL;
} else {
VN_RELE(rootvp);
}
fail_unmount:
VFS_UNMOUNT(vfsp, 0, NULL, error);
fail_vfsop:
vfs_deallocate(vfsp);
out_null:
kfree(args);
return -error;
printk(KERN_WARNING "%s: cache still in use!\n", __FUNCTION__);
}
/*
......@@ -789,8 +595,7 @@ linvfs_write_super(
sb->s_dirt = 0;
if (sb->s_flags & MS_RDONLY)
return;
VFS_SYNC(vfsp, SYNC_FSDATA|SYNC_BDFLUSH|SYNC_ATTR,
NULL, error);
VFS_SYNC(vfsp, SYNC_FSDATA|SYNC_BDFLUSH|SYNC_ATTR, NULL, error);
}
STATIC int
......@@ -811,30 +616,21 @@ linvfs_remount(
int *flags,
char *options)
{
struct xfs_mount_args *args;
vfs_t *vfsp;
xfs_mount_t *mp;
int error = 0;
vfsp = LINVFS_GET_VFS(sb);
mp = XFS_BHVTOM(vfsp->vfs_fbhv);
vfs_t *vfsp = LINVFS_GET_VFS(sb);
xfs_mount_t *mp = XFS_VFSTOM(vfsp);
struct xfs_mount_args *args = args_allocate(sb);
int error;
args = kmalloc(sizeof(struct xfs_mount_args), GFP_KERNEL);
if (!args)
return -ENOMEM;
memset(args, 0, sizeof(struct xfs_mount_args));
args->slcount = args->stimeout = args->ctimeout = -1;
if (xfs_parseargs(options, *flags, args)) {
error = -EINVAL;
VFS_PARSEARGS(vfsp, options, args, 1, error);
if (error)
goto out;
}
if (args->flags & XFSMNT_NOATIME)
mp->m_flags |= XFS_MOUNT_NOATIME;
else
mp->m_flags &= ~XFS_MOUNT_NOATIME;
set_posix_acl(sb);
set_posix_acl_flag(sb);
linvfs_write_super(sb);
if ((*flags & MS_RDONLY) == (sb->s_flags & MS_RDONLY))
......@@ -842,14 +638,14 @@ linvfs_remount(
if (*flags & MS_RDONLY) {
sb->s_flags |= MS_RDONLY;
XFS_log_write_unmount_ro(vfsp->vfs_fbhv);
XFS_log_write_unmount_ro(&mp->m_bhv);
vfsp->vfs_flag |= VFS_RDONLY;
} else {
vfsp->vfs_flag &= ~VFS_RDONLY;
}
out:
kfree(args);
kmem_free(args, sizeof(*args));
return error;
}
......@@ -950,6 +746,151 @@ linvfs_get_dentry(
return result;
}
STATIC int
linvfs_show_options(
struct seq_file *m,
struct vfsmount *mnt)
{
struct vfs *vfsp = LINVFS_GET_VFS(mnt->mnt_sb);
int error;
VFS_SHOWARGS(vfsp, m, error);
return error;
}
STATIC int
linvfs_getxstate(
struct super_block *sb,
struct fs_quota_stat *fqs)
{
struct vfs *vfsp = LINVFS_GET_VFS(sb);
int error;
VFS_QUOTACTL(vfsp, Q_XGETQSTAT, 0, (caddr_t)fqs, error);
return -error;
}
STATIC int
linvfs_setxstate(
struct super_block *sb,
unsigned int flags,
int op)
{
struct vfs *vfsp = LINVFS_GET_VFS(sb);
int error;
VFS_QUOTACTL(vfsp, op, 0, (caddr_t)&flags, error);
return -error;
}
STATIC int
linvfs_getxquota(
struct super_block *sb,
int type,
qid_t id,
struct fs_disk_quota *fdq)
{
struct vfs *vfsp = LINVFS_GET_VFS(sb);
int error, getmode;
getmode = (type == GRPQUOTA) ? Q_XGETGQUOTA : Q_XGETQUOTA;
VFS_QUOTACTL(vfsp, getmode, id, (caddr_t)fdq, error);
return -error;
}
STATIC int
linvfs_setxquota(
struct super_block *sb,
int type,
qid_t id,
struct fs_disk_quota *fdq)
{
struct vfs *vfsp = LINVFS_GET_VFS(sb);
int error, setmode;
setmode = (type == GRPQUOTA) ? Q_XSETGQLIM : Q_XSETQLIM;
VFS_QUOTACTL(vfsp, setmode, id, (caddr_t)fdq, error);
return -error;
}
STATIC int
linvfs_fill_super(
struct super_block *sb,
void *data,
int silent)
{
vnode_t *rootvp;
struct vfs *vfsp = vfs_allocate();
struct xfs_mount_args *args = args_allocate(sb);
struct statfs statvfs;
int error;
vfsp->vfs_super = sb;
LINVFS_SET_VFS(sb, vfsp);
if (sb->s_flags & MS_RDONLY)
vfsp->vfs_flag |= VFS_RDONLY;
bhv_insert_all_vfsops(vfsp);
VFS_PARSEARGS(vfsp, (char *)data, args, 0, error);
if (error) {
bhv_remove_all_vfsops(vfsp, 1);
goto fail_vfsop;
}
sb_min_blocksize(sb, BBSIZE);
sb->s_maxbytes = XFS_MAX_FILE_OFFSET;
sb->s_export_op = &linvfs_export_ops;
sb->s_qcop = &linvfs_qops;
sb->s_op = &linvfs_sops;
VFS_MOUNT(vfsp, args, NULL, error);
if (error) {
bhv_remove_all_vfsops(vfsp, 1);
goto fail_vfsop;
}
VFS_STATVFS(vfsp, &statvfs, NULL, error);
if (error)
goto fail_unmount;
sb->s_dirt = 1;
sb->s_magic = XFS_SB_MAGIC;
sb->s_blocksize = statvfs.f_bsize;
sb->s_blocksize_bits = ffs(statvfs.f_bsize) - 1;
set_posix_acl_flag(sb);
VFS_ROOT(vfsp, &rootvp, error);
if (error)
goto fail_unmount;
sb->s_root = d_alloc_root(LINVFS_GET_IP(rootvp));
if (!sb->s_root)
goto fail_vnrele;
if (is_bad_inode(sb->s_root->d_inode))
goto fail_vnrele;
vn_trace_exit(rootvp, __FUNCTION__, (inst_t *)__return_address);
kmem_free(args, sizeof(*args));
return 0;
fail_vnrele:
if (sb->s_root) {
dput(sb->s_root);
sb->s_root = NULL;
} else {
VN_RELE(rootvp);
}
fail_unmount:
VFS_UNMOUNT(vfsp, 0, NULL, error);
fail_vfsop:
vfs_deallocate(vfsp);
kmem_free(args, sizeof(*args));
return -error;
}
STATIC struct super_block *
linvfs_get_sb(
struct file_system_type *fs_type,
......@@ -960,15 +901,6 @@ linvfs_get_sb(
return get_sb_bdev(fs_type, flags, dev_name, data, linvfs_fill_super);
}
STATIC int
linvfs_show_options(
struct seq_file *m,
struct vfsmount *mnt)
{
vfs_t *vfsp = LINVFS_GET_VFS(mnt->mnt_sb);
return xfs_showargs(vfsp, m);
}
STATIC struct export_operations linvfs_export_ops = {
.get_parent = linvfs_get_parent,
......@@ -989,6 +921,13 @@ STATIC struct super_operations linvfs_sops = {
.show_options = linvfs_show_options,
};
STATIC struct quotactl_ops linvfs_qops = {
.get_xstate = linvfs_getxstate,
.set_xstate = linvfs_setxstate,
.get_xquota = linvfs_getxquota,
.set_xquota = linvfs_setxquota,
};
STATIC struct file_system_type xfs_fs_type = {
.owner = THIS_MODULE,
.name = "xfs",
......@@ -997,6 +936,50 @@ STATIC struct file_system_type xfs_fs_type = {
.fs_flags = FS_REQUIRES_DEV,
};
void
bhv_remove_vfsops(
struct vfs *vfsp,
int pos)
{
struct bhv_desc *bhv;
bhv = bhv_lookup_range(&vfsp->vfs_bh, pos, pos);
if (!bhv)
return;
bhv_remove(&vfsp->vfs_bh, bhv);
kmem_free(bhv, sizeof(*bhv));
}
void
bhv_remove_all_vfsops(
struct vfs *vfsp,
int freebase)
{
struct xfs_mount *mp;
bhv_remove_vfsops(vfsp, VFS_POSITION_QM);
bhv_remove_vfsops(vfsp, VFS_POSITION_DM);
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 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);
}
STATIC int __init
init_xfs_fs( void )
{
......@@ -1008,37 +991,49 @@ init_xfs_fs( void )
printk(message);
error = init_inodecache();
if (error < 0)
return error;
si_meminfo(&si);
xfs_physmem = si.totalram;
error = init_inodecache();
if (error < 0)
goto undo_inodecache;
error = pagebuf_init();
if (error < 0)
goto out;
goto undo_pagebuf;
error = vfs_initdmapi();
if (error < 0)
goto undo_dmapi;
error = vfs_initquota();
if (error < 0)
goto undo_quota;
vn_init();
xfs_init();
dmapi_init();
error = register_filesystem(&xfs_fs_type);
if (error)
goto out;
goto undo_fs;
return 0;
out:
undo_fs:
vfs_exitquota();
undo_quota:
vfs_exitdmapi();
undo_dmapi:
pagebuf_terminate();
undo_pagebuf:
destroy_inodecache();
undo_inodecache:
return error;
}
STATIC void __exit
exit_xfs_fs( void )
{
dmapi_uninit();
xfs_cleanup();
unregister_filesystem(&xfs_fs_type);
vfs_exitquota();
vfs_exitdmapi();
pagebuf_terminate();
destroy_inodecache();
}
......@@ -1047,5 +1042,6 @@ module_init(init_xfs_fs);
module_exit(exit_xfs_fs);
MODULE_AUTHOR("SGI <sgi.com>");
MODULE_DESCRIPTION("SGI XFS " XFS_VERSION_STRING " with " XFS_BUILD_OPTIONS " enabled");
MODULE_DESCRIPTION(
"SGI XFS " XFS_VERSION_STRING " with " XFS_BUILD_OPTIONS " enabled");
MODULE_LICENSE("GPL");
/*
* Copyright (c) 2000-2002 Silicon Graphics, Inc. All Rights Reserved.
* 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
......@@ -34,20 +34,34 @@
#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_DMAPI
# define XFS_DMAPI_STRING "DMAPI, "
# define vfs_insertdmapi(vfs) vfs_insertops(vfsp, &xfs_dmops_xfs)
# define vfs_initdmapi() (0) /* temporarily */
# define vfs_exitdmapi() do { } while (0) /* temporarily */
#else
# define XFS_DMAPI_STRING
# define vfs_insertdmapi(vfs) do { } while (0)
# define vfs_initdmapi() (0)
# define vfs_exitdmapi() do { } while (0)
#endif
#ifdef CONFIG_XFS_QUOTA
# define XFS_QUOTA_STRING "quota, "
# define vfs_insertquota(vfs) vfs_insertops(vfsp, &xfs_qmops_xfs)
# define vfs_initquota() (0) /* temporarily */
# define vfs_exitquota() do { } while (0) /* temporarily */
#else
# define XFS_QUOTA_STRING
# define vfs_insertquota(vfs) do { } while (0)
# define vfs_initquota() (0)
# define vfs_exitquota() do { } while (0)
#endif
#ifdef CONFIG_XFS_RT
......@@ -82,6 +96,8 @@ struct xfs_mount;
struct pb_target;
struct block_device;
extern int xfs_parseargs(bhv_desc_t *, char *, struct xfs_mount_args *, int);
extern int xfs_showargs(bhv_desc_t *, struct seq_file *);
extern void xfs_initialize_vnode(bhv_desc_t *, vnode_t *, bhv_desc_t *, int);
extern int xfs_blkdev_get(struct xfs_mount *, const char *,
......@@ -95,4 +111,8 @@ extern void xfs_free_buftarg(struct pb_target *);
extern void xfs_setsize_buftarg(struct pb_target *, unsigned int, unsigned int);
extern unsigned int xfs_getsize_buftarg(struct pb_target *);
extern void bhv_insert_all_vfsops(struct vfs *);
extern void bhv_remove_all_vfsops(struct vfs *, int);
extern void bhv_remove_vfsops(struct vfs *, int);
#endif /* __XFS_SUPER_H__ */
/*
* 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>
int
vfs_mount(bhv_desc_t *bdp, struct xfs_mount_args *args, struct cred *cr)
{
bhv_desc_t *next = bdp;
ASSERT(next);
while (! (bhvtovfsops(next))->vfs_mount)
next = BHV_NEXT(next);
return ((*bhvtovfsops(next)->vfs_mount)(next, args, cr));
}
int
vfs_parseargs(bhv_desc_t *bdp, char *s, struct xfs_mount_args *args, int f)
{
bhv_desc_t *next = bdp;
ASSERT(next);
while (! (bhvtovfsops(next))->vfs_parseargs)
next = BHV_NEXT(next);
return ((*bhvtovfsops(next)->vfs_parseargs)(next, s, args, f));
}
int
vfs_showargs(bhv_desc_t *bdp, struct seq_file *m)
{
bhv_desc_t *next = bdp;
ASSERT(next);
while (! (bhvtovfsops(next))->vfs_showargs)
next = BHV_NEXT(next);
return ((*bhvtovfsops(next)->vfs_showargs)(next, m));
}
int
vfs_unmount(bhv_desc_t *bdp, int fl, struct cred *cr)
{
bhv_desc_t *next = bdp;
ASSERT(next);
while (! (bhvtovfsops(next))->vfs_unmount)
next = BHV_NEXT(next);
return ((*bhvtovfsops(next)->vfs_unmount)(next, fl, cr));
}
int
vfs_root(bhv_desc_t *bdp, struct vnode **vpp)
{
bhv_desc_t *next = bdp;
ASSERT(next);
while (! (bhvtovfsops(next))->vfs_root)
next = BHV_NEXT(next);
return ((*bhvtovfsops(next)->vfs_root)(next, vpp));
}
int
vfs_statvfs(bhv_desc_t *bdp, struct statfs *sp, struct vnode *vp)
{
bhv_desc_t *next = bdp;
ASSERT(next);
while (! (bhvtovfsops(next))->vfs_statvfs)
next = BHV_NEXT(next);
return ((*bhvtovfsops(next)->vfs_statvfs)(next, sp, vp));
}
int
vfs_sync(bhv_desc_t *bdp, int fl, struct cred *cr)
{
bhv_desc_t *next = bdp;
ASSERT(next);
while (! (bhvtovfsops(next))->vfs_sync)
next = BHV_NEXT(next);
return ((*bhvtovfsops(next)->vfs_sync)(next, fl, cr));
}
int
vfs_vget(bhv_desc_t *bdp, struct vnode **vpp, struct fid *fidp)
{
bhv_desc_t *next = bdp;
ASSERT(next);
while (! (bhvtovfsops(next))->vfs_vget)
next = BHV_NEXT(next);
return ((*bhvtovfsops(next)->vfs_vget)(next, vpp, fidp));
}
int
vfs_dmapiops(bhv_desc_t *bdp, caddr_t addr)
{
bhv_desc_t *next = bdp;
ASSERT(next);
while (! (bhvtovfsops(next))->vfs_dmapiops)
next = BHV_NEXT(next);
return ((*bhvtovfsops(next)->vfs_dmapiops)(next, addr));
}
int
vfs_quotactl(bhv_desc_t *bdp, int cmd, int id, caddr_t addr)
{
bhv_desc_t *next = bdp;
ASSERT(next);
while (! (bhvtovfsops(next))->vfs_quotactl)
next = BHV_NEXT(next);
return ((*bhvtovfsops(next)->vfs_quotactl)(next, cmd, id, addr));
}
void
vfs_init_vnode(bhv_desc_t *bdp, struct vnode *vp, bhv_desc_t *bp, int unlock)
{
bhv_desc_t *next = bdp;
ASSERT(next);
while (! (bhvtovfsops(next))->vfs_init_vnode)
next = BHV_NEXT(next);
((*bhvtovfsops(next)->vfs_init_vnode)(next, vp, bp, unlock));
}
void
vfs_force_shutdown(bhv_desc_t *bdp, int fl, char *file, int line)
{
bhv_desc_t *next = bdp;
ASSERT(next);
while (! (bhvtovfsops(next))->vfs_force_shutdown)
next = BHV_NEXT(next);
((*bhvtovfsops(next)->vfs_force_shutdown)(next, fl, file, line));
}
vfs_t *
vfs_allocate(void)
{
vfs_t *vfsp = kmem_zalloc(sizeof(vfs_t), KM_SLEEP);
bhv_head_init(VFS_BHVHEAD(vfsp), "vfs");
return vfsp;
}
void
vfs_deallocate(vfs_t *vfsp)
{
bhv_head_destroy(VFS_BHVHEAD(vfsp));
kmem_free(vfsp, sizeof(vfs_t));
}
void
vfs_insertops(vfs_t *vfsp, vfsops_t *vfsops)
{
bhv_desc_t *bdp = kmem_alloc(sizeof(bhv_desc_t), KM_SLEEP);
bhv_desc_init(bdp, NULL, vfsp, vfsops);
bhv_insert(&vfsp->vfs_bh, bdp);
}
void
vfs_insertbhv(vfs_t *vfsp, bhv_desc_t *bdp, vfsops_t *vfsops, void *mount)
{
bhv_desc_init(bdp, mount, vfsp, vfsops);
bhv_insert_initial(&vfsp->vfs_bh, bdp);
}
/*
* Copyright (c) 2000-2002 Silicon Graphics, Inc. All Rights Reserved.
* 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
......@@ -34,34 +34,51 @@
#include <linux/vfs.h>
struct statfs;
struct vnode;
struct fid;
struct cred;
struct vnode;
struct statfs;
struct seq_file;
struct super_block;
struct fid;
struct dm_fcntl_vector;
struct xfs_mount_args;
typedef struct vfs {
u_int vfs_flag; /* flags */
fsid_t vfs_fsid; /* file system id */
fsid_t vfs_fsid; /* file system ID */
fsid_t *vfs_altfsid; /* An ID fixed for life of FS */
bhv_head_t vfs_bh; /* head of vfs behavior chain */
struct super_block *vfs_super; /* pointer to super block structure */
struct super_block *vfs_super; /* Linux superblock structure */
} vfs_t;
#define vfs_fbhv vfs_bh.bh_first /* 1st on vfs behavior chain */
#define VFS_FOPS(vfsp) \
((vfsops_t *)((vfsp)->vfs_fbhv->bd_ops))/* ops for 1st behavior */
#define bhvtovfs(bdp) ((struct vfs *)BHV_VOBJ(bdp))
#define VFS_BHVHEAD(vfsp) (&(vfsp)->vfs_bh)
#define bhvtovfs(bdp) ( (struct vfs *)BHV_VOBJ(bdp) )
#define bhvtovfsops(bdp) ( (struct vfsops *)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_END 0x0004 /* max flag */
#define SYNC_ATTR 0x0001 /* sync attributes */
#define SYNC_CLOSE 0x0002 /* close file system down */
......@@ -70,126 +87,87 @@ typedef struct vfs {
#define SYNC_FSDATA 0x0020 /* flush fs data (e.g. superblocks) */
#define SYNC_BDFLUSH 0x0010 /* BDFLUSH is calling -- don't block */
typedef int (*vfs_mount_t)(bhv_desc_t *,
struct xfs_mount_args *, struct cred *);
typedef int (*vfs_parseargs_t)(bhv_desc_t *, char *,
struct xfs_mount_args *, int);
typedef int (*vfs_showargs_t)(bhv_desc_t *, struct seq_file *);
typedef int (*vfs_unmount_t)(bhv_desc_t *, int, struct cred *);
typedef int (*vfs_root_t)(bhv_desc_t *, struct vnode **);
typedef int (*vfs_statvfs_t)(bhv_desc_t *, struct statfs *, struct vnode *);
typedef int (*vfs_sync_t)(bhv_desc_t *, int, struct cred *);
typedef int (*vfs_vget_t)(bhv_desc_t *, struct vnode **, struct fid *);
typedef int (*vfs_dmapiops_t)(bhv_desc_t *, caddr_t);
typedef int (*vfs_quotactl_t)(bhv_desc_t *, int, int, caddr_t);
typedef void (*vfs_init_vnode_t)(bhv_desc_t *,
struct vnode *, bhv_desc_t *, int);
typedef void (*vfs_force_shutdown_t)(bhv_desc_t *, int, char *, int);
typedef struct vfsops {
int (*vfs_mount)(struct vfs *, struct xfs_mount_args *,
struct cred *);
/* mount file system */
int (*vfs_unmount)(bhv_desc_t *, int, struct cred *);
/* unmount file system */
int (*vfs_root)(bhv_desc_t *, struct vnode **);
/* get root vnode */
int (*vfs_statvfs)(bhv_desc_t *, struct statfs *, struct vnode *);
/* get file system statistics */
int (*vfs_sync)(bhv_desc_t *, int, struct cred *);
/* flush files */
int (*vfs_vget)(bhv_desc_t *, struct vnode **, struct fid *);
/* get vnode from fid */
int (*vfs_dmapi_mount)(struct vfs *, char *, char *);
/* send dmapi mount event */
int (*vfs_dmapi_fsys_vector)(bhv_desc_t *,
struct dm_fcntl_vector *);
void (*vfs_init_vnode)(bhv_desc_t *, struct vnode *,
bhv_desc_t *, int);
void (*vfs_force_shutdown)(bhv_desc_t *,
int, char *, int);
bhv_position_t vf_position; /* behavior chain position */
vfs_mount_t vfs_mount; /* mount file system */
vfs_parseargs_t vfs_parseargs; /* parse mount options */
vfs_showargs_t vfs_showargs; /* unparse mount options */
vfs_unmount_t vfs_unmount; /* unmount file system */
vfs_root_t vfs_root; /* get root vnode */
vfs_statvfs_t vfs_statvfs; /* file system statistics */
vfs_sync_t vfs_sync; /* flush files */
vfs_vget_t vfs_vget; /* get vnode from fid */
vfs_dmapiops_t vfs_dmapiops; /* data migration */
vfs_quotactl_t vfs_quotactl; /* disk quota */
vfs_init_vnode_t vfs_init_vnode; /* initialize a new vnode */
vfs_force_shutdown_t vfs_force_shutdown; /* crash and burn */
} vfsops_t;
#define VFS_UNMOUNT(vfsp,f,cr, rv) \
{ \
rv = (*(VFS_FOPS(vfsp)->vfs_unmount))((vfsp)->vfs_fbhv, f, cr); \
}
#define VFS_ROOT(vfsp, vpp, rv) \
{ \
rv = (*(VFS_FOPS(vfsp)->vfs_root))((vfsp)->vfs_fbhv, vpp); \
}
#define VFS_STATVFS(vfsp, sp, vp, rv) \
{ \
rv = (*(VFS_FOPS(vfsp)->vfs_statvfs))((vfsp)->vfs_fbhv, sp, vp);\
}
#define VFS_SYNC(vfsp, flag, cr, rv) \
{ \
rv = (*(VFS_FOPS(vfsp)->vfs_sync))((vfsp)->vfs_fbhv, flag, cr); \
}
#define VFS_VGET(vfsp, vpp, fidp, rv) \
{ \
rv = (*(VFS_FOPS(vfsp)->vfs_vget))((vfsp)->vfs_fbhv, vpp, fidp); \
}
#define VFS_INIT_VNODE(vfsp, vp, bhv, unlock) \
{ \
(*(VFS_FOPS(vfsp)->vfs_init_vnode))((vfsp)->vfs_fbhv, vp, bhv, unlock);\
}
/* No behavior lock here */
#define VFS_FORCE_SHUTDOWN(vfsp, flags) \
(*(VFS_FOPS(vfsp)->vfs_force_shutdown))((vfsp)->vfs_fbhv, flags, __FILE__, __LINE__);
#define VFS_DMAPI_FSYS_VECTOR(vfsp, df, rv) \
{ \
rv = (*(VFS_FOPS(vfsp)->vfs_dmapi_fsys_vector))((vfsp)->vfs_fbhv, df); \
}
#define VFSOPS_DMAPI_MOUNT(vfs_op, vfsp, dir_name, fsname, rv) \
rv = (*(vfs_op)->vfs_dmapi_mount)(vfsp, dir_name, fsname)
#define VFSOPS_MOUNT(vfs_op, vfsp, args, cr, rv) \
rv = (*(vfs_op)->vfs_mount)(vfsp, args, cr)
#define VFS_REMOVEBHV(vfsp, bdp)\
{ \
bhv_remove(VFS_BHVHEAD(vfsp), bdp); \
}
#define PVFS_UNMOUNT(bdp,f,cr, rv) \
{ \
rv = (*((vfsops_t *)(bdp)->bd_ops)->vfs_unmount)(bdp, f, cr); \
}
#define PVFS_SYNC(bdp, flag, cr, rv) \
{ \
rv = (*((vfsops_t *)(bdp)->bd_ops)->vfs_sync)(bdp, flag, cr); \
}
static __inline vfs_t *
vfs_allocate(void)
{
vfs_t *vfsp;
vfsp = kmalloc(sizeof(vfs_t), GFP_KERNEL);
if (vfsp) {
memset(vfsp, 0, sizeof(vfs_t));
bhv_head_init(VFS_BHVHEAD(vfsp), "vfs");
}
return (vfsp);
}
static __inline void
vfs_deallocate(
vfs_t *vfsp)
{
bhv_head_destroy(VFS_BHVHEAD(vfsp));
kfree(vfsp);
}
/*
* Called by fs dependent VFS_MOUNT code to link the VFS base file system
* dependent behavior with the VFS virtual object.
* VFS's. Operates on vfs structure pointers (starts at bhv head).
*/
static __inline void
vfs_insertbhv(
vfs_t *vfsp,
bhv_desc_t *bdp,
vfsops_t *vfsops,
void *mount)
{
/*
* Initialize behavior desc with ops and data and then
* attach it to the vfs.
#define VHEAD(v) ((v)->vfs_fbhv)
#define VFS_MOUNT(v, ma,cr, rv) ((rv) = vfs_mount(VHEAD(v), ma,cr))
#define VFS_PARSEARGS(v, o,ma,f, rv) ((rv) = vfs_parseargs(VHEAD(v), o,ma,f))
#define VFS_SHOWARGS(v, m, rv) ((rv) = vfs_showargs(VHEAD(v), m))
#define VFS_UNMOUNT(v, f,cr, rv) ((rv) = vfs_unmount(VHEAD(v), f,cr))
#define VFS_ROOT(v, vpp, rv) ((rv) = vfs_root(VHEAD(v), vpp))
#define VFS_STATVFS(v, sp,vp, rv) ((rv) = vfs_statvfs(VHEAD(v), sp,vp))
#define VFS_SYNC(v, flag,cr, rv) ((rv) = vfs_sync(VHEAD(v), flag,cr))
#define VFS_VGET(v, vpp,fidp, rv) ((rv) = vfs_vget(VHEAD(v), vpp,fidp))
#define VFS_DMAPIOPS(v, p, rv) ((rv) = vfs_dmapiops(VHEAD(v), p))
#define VFS_QUOTACTL(v, c,id,p, rv) ((rv) = vfs_quotactl(VHEAD(v), c,id,p))
#define VFS_INIT_VNODE(v, vp,b,ul) ( vfs_init_vnode(VHEAD(v), vp,b,ul) )
#define VFS_FORCE_SHUTDOWN(v, fl,f,l) ( vfs_force_shutdown(VHEAD(v), fl,f,l) )
/*
* PVFS's. Operates on behavior descriptor pointers.
*/
bhv_desc_init(bdp, mount, vfsp, vfsops);
bhv_insert_initial(&vfsp->vfs_bh, bdp);
}
#define PVFS_MOUNT(b, ma,cr, rv) ((rv) = vfs_mount(b, ma,cr))
#define PVFS_PARSEARGS(b, o,ma,f, rv) ((rv) = vfs_parseargs(b, o,ma,f))
#define PVFS_SHOWARGS(b, m, rv) ((rv) = vfs_showargs(b, m))
#define PVFS_UNMOUNT(b, f,cr, rv) ((rv) = vfs_unmount(b, f,cr))
#define PVFS_ROOT(b, vpp, rv) ((rv) = vfs_root(b, vpp))
#define PVFS_STATVFS(b, sp,vp, rv) ((rv) = vfs_statvfs(b, sp,vp))
#define PVFS_SYNC(b, flag,cr, rv) ((rv) = vfs_sync(b, flag,cr))
#define PVFS_VGET(b, vpp,fidp, rv) ((rv) = vfs_vget(b, vpp,fidp))
#define PVFS_DMAPIOPS(b, p, rv) ((rv) = vfs_dmapiops(b, p))
#define PVFS_QUOTACTL(b, c,id,p, rv) ((rv) = vfs_quotactl(b, c,id,p))
#define PVFS_INIT_VNODE(b, vp,b2,ul) ( vfs_init_vnode(b, vp,b2,ul) )
#define PVFS_FORCE_SHUTDOWN(b, fl,f,l) ( vfs_force_shutdown(b, fl,f,l) )
extern int vfs_mount(bhv_desc_t *, struct xfs_mount_args *, struct cred *);
extern int vfs_parseargs(bhv_desc_t *, char *, struct xfs_mount_args *, int);
extern int vfs_showargs(bhv_desc_t *, struct seq_file *);
extern int vfs_unmount(bhv_desc_t *, int, struct cred *);
extern int vfs_root(bhv_desc_t *, struct vnode **);
extern int vfs_statvfs(bhv_desc_t *, struct statfs *, struct vnode *);
extern int vfs_sync(bhv_desc_t *, int, struct cred *);
extern int vfs_vget(bhv_desc_t *, struct vnode **, struct fid *);
extern int vfs_dmapiops(bhv_desc_t *, caddr_t);
extern int vfs_quotactl(bhv_desc_t *, int, int, caddr_t);
extern void vfs_init_vnode(bhv_desc_t *, struct vnode *, bhv_desc_t *, int);
extern void vfs_force_shutdown(bhv_desc_t *, int, char *, int);
extern vfs_t *vfs_allocate(void);
extern void vfs_deallocate(vfs_t *);
extern void vfs_insertops(vfs_t *, vfsops_t *);
extern void vfs_insertbhv(vfs_t *, bhv_desc_t *, vfsops_t *, void *);
#endif /* __XFS_VFS_H__ */
/*
* Copyright (c) 2000-2002 Silicon Graphics, Inc. All Rights Reserved.
* 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
......@@ -85,10 +85,16 @@ typedef struct vnode {
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)
/*
* Macros for dealing with the behavior descriptor inside of the vnode.
......@@ -96,7 +102,6 @@ typedef enum {
#define BHV_TO_VNODE(bdp) ((vnode_t *)BHV_VOBJ(bdp))
#define BHV_TO_VNODE_NULL(bdp) ((vnode_t *)BHV_VOBJNULL(bdp))
#define VNODE_TO_FIRST_BHV(vp) (BHV_HEAD_FIRST(&(vp)->v_bh))
#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)
......@@ -127,16 +132,6 @@ extern ushort vttoif_tab[];
#define VWAIT 0x4 /* waiting for VINACT/VRECLM to end */
#define VMODIFIED 0x8 /* XFS inode state possibly differs */
/* to the Linux inode state. */
#define VROOT 0x100000 /* root of its file system */
#define VNOSWAP 0x200000 /* cannot be used as virt swap device */
#define VISSWAP 0x400000 /* vnode is part of virt swap device */
#define VREPLICABLE 0x800000 /* Vnode can have replicated pages */
#define VNONREPLICABLE 0x1000000 /* Vnode has writers. Don't replicate */
#define VDOCMP 0x2000000 /* Vnode has special VOP_CMP impl. */
#define VSHARE 0x4000000 /* vnode part of global cache */
#define VFRLOCKS 0x8000000 /* vnode has FR locks applied */
#define VENF_LOCKING 0x10000000 /* enf. mode FR locking in effect */
#define VOPLOCK 0x20000000 /* oplock set on the vnode */
typedef enum vrwlock { VRWLOCK_NONE, VRWLOCK_READ,
VRWLOCK_WRITE, VRWLOCK_WRITE_DIRECT,
......@@ -268,162 +263,91 @@ typedef struct vnodeops {
#define _VOP_(op, vp) (*((vnodeops_t *)(vp)->v_fops)->op)
#define VOP_READ(vp,file,iov,segs,offset,cr,rv) \
{ \
rv = _VOP_(vop_read, vp)((vp)->v_fbhv,file,iov,segs,offset,cr); \
}
rv = _VOP_(vop_read, vp)((vp)->v_fbhv,file,iov,segs,offset,cr)
#define VOP_WRITE(vp,file,iov,segs,offset,cr,rv) \
{ \
rv = _VOP_(vop_write, vp)((vp)->v_fbhv,file,iov,segs,offset,cr);\
}
#define VOP_SENDFILE(vp,f,of,cnt,act,targ,cr,rv) \
{ \
rv = _VOP_(vop_sendfile, vp)((vp)->v_fbhv,f,of,cnt,act,targ,cr);\
}
rv = _VOP_(vop_write, vp)((vp)->v_fbhv,file,iov,segs,offset,cr)
#define VOP_SENDFILE(vp,f,off,cnt,act,targ,cr,rv) \
rv = _VOP_(vop_sendfile, vp)((vp)->v_fbhv,f,off,cnt,act,targ,cr)
#define VOP_BMAP(vp,of,sz,rw,b,n,rv) \
{ \
rv = _VOP_(vop_bmap, vp)((vp)->v_fbhv,of,sz,rw,b,n); \
}
rv = _VOP_(vop_bmap, vp)((vp)->v_fbhv,of,sz,rw,b,n)
#define VOP_OPEN(vp, cr, rv) \
{ \
rv = _VOP_(vop_open, vp)((vp)->v_fbhv, cr); \
}
rv = _VOP_(vop_open, vp)((vp)->v_fbhv, cr)
#define VOP_GETATTR(vp, vap, f, cr, rv) \
{ \
rv = _VOP_(vop_getattr, vp)((vp)->v_fbhv, vap, f, cr); \
}
rv = _VOP_(vop_getattr, vp)((vp)->v_fbhv, vap, f, cr)
#define VOP_SETATTR(vp, vap, f, cr, rv) \
{ \
rv = _VOP_(vop_setattr, vp)((vp)->v_fbhv, vap, f, cr); \
}
rv = _VOP_(vop_setattr, vp)((vp)->v_fbhv, vap, f, cr)
#define VOP_ACCESS(vp, mode, cr, rv) \
{ \
rv = _VOP_(vop_access, vp)((vp)->v_fbhv, mode, cr); \
}
rv = _VOP_(vop_access, vp)((vp)->v_fbhv, mode, cr)
#define VOP_LOOKUP(vp,d,vpp,f,rdir,cr,rv) \
{ \
rv = _VOP_(vop_lookup, vp)((vp)->v_fbhv,d,vpp,f,rdir,cr); \
}
rv = _VOP_(vop_lookup, vp)((vp)->v_fbhv,d,vpp,f,rdir,cr)
#define VOP_CREATE(dvp,d,vap,vpp,cr,rv) \
{ \
rv = _VOP_(vop_create, dvp)((dvp)->v_fbhv,d,vap,vpp,cr); \
}
rv = _VOP_(vop_create, dvp)((dvp)->v_fbhv,d,vap,vpp,cr)
#define VOP_REMOVE(dvp,d,cr,rv) \
{ \
rv = _VOP_(vop_remove, dvp)((dvp)->v_fbhv,d,cr); \
}
rv = _VOP_(vop_remove, dvp)((dvp)->v_fbhv,d,cr)
#define VOP_LINK(tdvp,fvp,d,cr,rv) \
{ \
rv = _VOP_(vop_link, tdvp)((tdvp)->v_fbhv,fvp,d,cr); \
}
rv = _VOP_(vop_link, tdvp)((tdvp)->v_fbhv,fvp,d,cr)
#define VOP_RENAME(fvp,fnm,tdvp,tnm,cr,rv) \
{ \
rv = _VOP_(vop_rename, fvp)((fvp)->v_fbhv,fnm,tdvp,tnm,cr); \
}
rv = _VOP_(vop_rename, fvp)((fvp)->v_fbhv,fnm,tdvp,tnm,cr)
#define VOP_MKDIR(dp,d,vap,vpp,cr,rv) \
{ \
rv = _VOP_(vop_mkdir, dp)((dp)->v_fbhv,d,vap,vpp,cr); \
}
rv = _VOP_(vop_mkdir, dp)((dp)->v_fbhv,d,vap,vpp,cr)
#define VOP_RMDIR(dp,d,cr,rv) \
{ \
rv = _VOP_(vop_rmdir, dp)((dp)->v_fbhv,d,cr); \
}
rv = _VOP_(vop_rmdir, dp)((dp)->v_fbhv,d,cr)
#define VOP_READDIR(vp,uiop,cr,eofp,rv) \
{ \
rv = _VOP_(vop_readdir, vp)((vp)->v_fbhv,uiop,cr,eofp); \
}
rv = _VOP_(vop_readdir, vp)((vp)->v_fbhv,uiop,cr,eofp)
#define VOP_SYMLINK(dvp,d,vap,tnm,vpp,cr,rv) \
{ \
rv = _VOP_(vop_symlink, dvp) ((dvp)->v_fbhv,d,vap,tnm,vpp,cr); \
}
rv = _VOP_(vop_symlink, dvp) ((dvp)->v_fbhv,d,vap,tnm,vpp,cr)
#define VOP_READLINK(vp,uiop,cr,rv) \
{ \
rv = _VOP_(vop_readlink, vp)((vp)->v_fbhv,uiop,cr); \
}
rv = _VOP_(vop_readlink, vp)((vp)->v_fbhv,uiop,cr)
#define VOP_FSYNC(vp,f,cr,b,e,rv) \
{ \
rv = _VOP_(vop_fsync, vp)((vp)->v_fbhv,f,cr,b,e); \
}
rv = _VOP_(vop_fsync, vp)((vp)->v_fbhv,f,cr,b,e)
#define VOP_INACTIVE(vp, cr, rv) \
{ \
rv = _VOP_(vop_inactive, vp)((vp)->v_fbhv, cr); \
}
rv = _VOP_(vop_inactive, vp)((vp)->v_fbhv, cr)
#define VOP_RELEASE(vp, rv) \
{ \
rv = _VOP_(vop_release, vp)((vp)->v_fbhv); \
}
rv = _VOP_(vop_release, vp)((vp)->v_fbhv)
#define VOP_FID2(vp, fidp, rv) \
{ \
rv = _VOP_(vop_fid2, vp)((vp)->v_fbhv, fidp); \
}
rv = _VOP_(vop_fid2, vp)((vp)->v_fbhv, fidp)
#define VOP_RWLOCK(vp,i) \
{ \
(void)_VOP_(vop_rwlock, vp)((vp)->v_fbhv, i); \
}
(void)_VOP_(vop_rwlock, vp)((vp)->v_fbhv, i)
#define VOP_RWLOCK_TRY(vp,i) \
_VOP_(vop_rwlock, vp)((vp)->v_fbhv, i)
#define VOP_RWUNLOCK(vp,i) \
{ \
(void)_VOP_(vop_rwunlock, vp)((vp)->v_fbhv, i); \
}
(void)_VOP_(vop_rwunlock, vp)((vp)->v_fbhv, i)
#define VOP_FRLOCK(vp,c,fl,flags,offset,fr,rv) \
rv = _VOP_(vop_frlock, vp)((vp)->v_fbhv,c,fl,flags,offset,fr)
#define VOP_RECLAIM(vp, rv) \
{ \
rv = _VOP_(vop_reclaim, vp)((vp)->v_fbhv); \
}
rv = _VOP_(vop_reclaim, vp)((vp)->v_fbhv)
#define VOP_ATTR_GET(vp, name, val, vallenp, fl, cred, rv) \
{ \
rv = _VOP_(vop_attr_get, vp)((vp)->v_fbhv,name,val,vallenp,fl,cred); \
}
rv = _VOP_(vop_attr_get, vp)((vp)->v_fbhv,name,val,vallenp,fl,cred)
#define VOP_ATTR_SET(vp, name, val, vallen, fl, cred, rv) \
{ \
rv = _VOP_(vop_attr_set, vp)((vp)->v_fbhv,name,val,vallen,fl,cred); \
}
rv = _VOP_(vop_attr_set, vp)((vp)->v_fbhv,name,val,vallen,fl,cred)
#define VOP_ATTR_REMOVE(vp, name, flags, cred, rv) \
{ \
rv = _VOP_(vop_attr_remove, vp)((vp)->v_fbhv,name,flags,cred); \
}
rv = _VOP_(vop_attr_remove, vp)((vp)->v_fbhv,name,flags,cred)
#define VOP_ATTR_LIST(vp, buf, buflen, fl, cursor, cred, rv) \
{ \
rv = _VOP_(vop_attr_list, vp)((vp)->v_fbhv,buf,buflen,fl,cursor,cred);\
}
rv = _VOP_(vop_attr_list, vp)((vp)->v_fbhv,buf,buflen,fl,cursor,cred)
#define VOP_LINK_REMOVED(vp, dvp, linkzero) \
{ \
(void)_VOP_(vop_link_removed, vp)((vp)->v_fbhv, dvp, linkzero); \
}
(void)_VOP_(vop_link_removed, vp)((vp)->v_fbhv, dvp, linkzero)
#define VOP_VNODE_CHANGE(vp, cmd, val) \
{ \
(void)_VOP_(vop_vnode_change, vp)((vp)->v_fbhv,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 VOP_TOSS_PAGES(vp, first, last, fiopt) \
{ \
_VOP_(vop_tosspages, vp)((vp)->v_fbhv,first, last, fiopt); \
}
_VOP_(vop_tosspages, vp)((vp)->v_fbhv,first, last, fiopt)
/*
* 'last' parameter is unused and left in for IRIX compatibility
*/
#define VOP_FLUSHINVAL_PAGES(vp, first, last, fiopt) \
{ \
_VOP_(vop_flushinval_pages, vp)((vp)->v_fbhv,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 VOP_FLUSH_PAGES(vp, first, last, flags, fiopt, rv) \
{ \
rv = _VOP_(vop_flush_pages, vp)((vp)->v_fbhv,first,last,flags,fiopt);\
}
rv = _VOP_(vop_flush_pages, vp)((vp)->v_fbhv,first,last,flags,fiopt)
#define VOP_IOCTL(vp, inode, filp, cmd, arg, rv) \
{ \
rv = _VOP_(vop_ioctl, vp)((vp)->v_fbhv,inode,filp,cmd,arg); \
}
rv = _VOP_(vop_ioctl, vp)((vp)->v_fbhv,inode,filp,cmd,arg)
#define VOP_IFLUSH(vp, flags, rv) \
{ \
rv = _VOP_(vop_iflush, vp)((vp)->v_fbhv, flags); \
}
rv = _VOP_(vop_iflush, vp)((vp)->v_fbhv, flags)
/*
* Flags for VOP_IFLUSH call
......
/*
* Copyright (c) 2000-2002 Silicon Graphics, Inc. All Rights Reserved.
* 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
......@@ -144,16 +144,10 @@
(1 << DM_EVENT_DESTROY) )
extern int
xfs_dm_mount(
vfs_t *vfsp,
char *dir_name,
char *fsname);
extern int
xfs_dm_get_fsys_vector(
bhv_desc_t *bdp,
dm_fcntl_vector_t *vecrq);
caddr_t vecrq);
extern int
xfs_dm_send_data_event(
......
/*
* 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>
#define MNTOPT_DMAPI "dmapi" /* DMI enabled (DMAPI / XDSM) */
#define MNTOPT_XDSM "xdsm" /* DMI enabled (DMAPI / XDSM) */
STATIC int
xfs_dm_parseargs(
struct bhv_desc *bhv,
char *options,
struct xfs_mount_args *args,
int update)
{
size_t length;
char *local_options = options;
char *this_char;
int error;
while ((this_char = strsep(&local_options, ",")) != NULL) {
length = strlen(this_char);
if (local_options)
length++;
if (!strcmp(this_char, MNTOPT_DMAPI)) {
args->flags |= XFSMNT_DMAPI;
} else if (!strcmp(this_char, MNTOPT_XDSM)) {
args->flags |= XFSMNT_DMAPI;
} else {
if (local_options)
*(local_options-1) = ',';
continue;
}
while (length--)
*this_char++ = ',';
}
PVFS_PARSEARGS(BHV_NEXT(bhv), options, args, update, error);
if (!error && (args->flags & XFSMNT_DMAPI) && (*args->mtpt == '\0'))
error = EINVAL;
if (!error && !update && !(args->flags & XFSMNT_DMAPI))
bhv_remove_vfsops(bhvtovfs(bhv), VFS_POSITION_DM);
return error;
}
STATIC int
xfs_dm_showargs(
struct bhv_desc *bhv,
struct seq_file *m)
{
struct vfs *vfsp = bhvtovfs(bhv);
int error;
if (vfsp->vfs_flag & VFS_DMI)
seq_puts(m, "," MNTOPT_DMAPI);
PVFS_SHOWARGS(BHV_NEXT(bhv), m, error);
return error;
}
STATIC int
xfs_dm_mount(
struct bhv_desc *bhv,
struct xfs_mount_args *args,
struct cred *cr)
{
struct bhv_desc *rootbdp;
struct vnode *rootvp;
struct vfs *vfsp;
int error = 0;
PVFS_MOUNT(BHV_NEXT(bhv), args, cr, error);
if (error)
return error;
if (args->flags & XFSMNT_DMAPI) {
vfsp = bhvtovfs(bhv);
VFS_ROOT(vfsp, &rootvp, error);
if (!error) {
vfsp->vfs_flag |= VFS_DMI;
rootbdp = vn_bhv_lookup_unlocked(
VN_BHV_HEAD(rootvp), &xfs_vnodeops);
VN_RELE(rootvp);
error = dm_send_mount_event(vfsp, DM_RIGHT_NULL, NULL,
DM_RIGHT_NULL, rootbdp, DM_RIGHT_NULL,
args->mtpt, args->fsname);
}
}
return error;
}
vfsops_t xfs_dmops_xfs = {
BHV_IDENTITY_INIT(VFS_BHV_DM, VFS_POSITION_DM),
.vfs_mount = xfs_dm_mount,
.vfs_parseargs = xfs_dm_parseargs,
.vfs_showargs = xfs_dm_showargs,
.vfs_dmapiops = xfs_dm_get_fsys_vector,
};
/*
* Copyright (c) 2000-2002 Silicon Graphics, Inc. All Rights Reserved.
* 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
......@@ -1190,25 +1190,6 @@ xfs_ialloc(
ip->i_d.di_aformat = XFS_DINODE_FMT_EXTENTS;
ip->i_d.di_anextents = 0;
#if DEBUG
{
uint badflags = VNOSWAP |
VISSWAP |
VREPLICABLE |
/* VNONREPLICABLE | XXX uncomment this */
VDOCMP |
VFRLOCKS;
/*
* For shared mounts, VNOSWAP is set in xfs_iget
*/
if (tp->t_mountp->m_cxfstype != XFS_CXFS_NOT)
badflags &= ~VNOSWAP;
ASSERT(!(vp->v_flag & badflags));
}
#endif /* DEBUG */
/*
* Log the new values stuffed into the inode.
*/
......
/*
* Copyright (c) 2000-2002 Silicon Graphics, Inc. All Rights Reserved.
* 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
......@@ -33,15 +33,25 @@
#include <xfs.h>
static xfs_fsize_t
STATIC xfs_fsize_t
xfs_size_fn(
xfs_inode_t *ip)
{
return (ip->i_d.di_size);
}
STATIC int
xfs_ioinit(
struct vfs *vfsp,
struct xfs_mount_args *mntargs,
int flags)
{
return xfs_mountfs(vfsp, XFS_VFSTOM(vfsp),
vfsp->vfs_super->s_bdev->bd_dev, flags);
}
xfs_ioops_t xfs_iocore_xfs = {
.xfs_ioinit = (xfs_ioinit_t) fs_noerr,
.xfs_ioinit = (xfs_ioinit_t) xfs_ioinit,
.xfs_bmapi_func = (xfs_bmapi_t) xfs_bmapi,
.xfs_bmap_eof_func = (xfs_bmap_eof_t) xfs_bmap_eof,
.xfs_iomap_write_direct =
......
/*
* Copyright (c) 2000-2002 Silicon Graphics, Inc. All Rights Reserved.
* 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
......@@ -358,6 +358,14 @@ xfs_bhvtom(bhv_desc_t *bdp)
}
#endif
#if XFS_WANT_FUNCS_C || (XFS_WANT_SPACE_C && XFSSO_XFS_VFSTOM)
xfs_mount_t *
xfs_vfstom(vfs_t *vfs)
{
return XFS_VFSTOM(vfs);
}
#endif
#if XFS_WANT_FUNCS_C || (XFS_WANT_SPACE_C && XFSSO_XFS_BM_MAXLEVELS)
int
xfs_bm_maxlevels(xfs_mount_t *mp, int w)
......
/*
* Copyright (c) 2000-2002 Silicon Graphics, Inc. All Rights Reserved.
* 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
......@@ -40,8 +40,6 @@ mutex_t xfs_uuidtabmon; /* monitor for uuidtab */
STATIC int xfs_uuidtab_size;
STATIC uuid_t *xfs_uuidtab;
STATIC void xfs_uuid_unmount(xfs_mount_t *);
void xfs_xlatesb(void *, xfs_sb_t *, int, xfs_arch_t, __int64_t);
static struct {
......@@ -120,10 +118,9 @@ xfs_mount_init(void)
spinlock_init(&mp->m_freeze_lock, "xfs_freeze");
init_sv(&mp->m_wait_unfreeze, SV_DEFAULT, "xfs_freeze", 0);
atomic_set(&mp->m_active_trans, 0);
mp->m_cxfstype = XFS_CXFS_NOT;
return mp;
} /* xfs_mount_init */
}
/*
* Free up the resources associated with a mount structure. Assume that
......@@ -146,19 +143,12 @@ xfs_mount_free(
for (agno = 0; agno < mp->m_maxagi; agno++)
if (mp->m_perag[agno].pagb_list)
kmem_free(mp->m_perag[agno].pagb_list,
sizeof(xfs_perag_busy_t) * XFS_PAGB_NUM_SLOTS);
sizeof(xfs_perag_busy_t) *
XFS_PAGB_NUM_SLOTS);
kmem_free(mp->m_perag,
sizeof(xfs_perag_t) * mp->m_sb.sb_agcount);
}
#if 0
/*
* XXXdpd - Doesn't work now for shutdown case.
* Should at least free the memory.
*/
ASSERT(mp->m_ail.ail_back == (xfs_log_item_t*)&(mp->m_ail));
ASSERT(mp->m_ail.ail_forw == (xfs_log_item_t*)&(mp->m_ail));
#endif
AIL_LOCK_DESTROY(&mp->m_ail_lock);
spinlock_destroy(&mp->m_sb_lock);
mutex_destroy(&mp->m_ilock);
......@@ -172,8 +162,12 @@ xfs_mount_free(
}
if (remove_bhv) {
VFS_REMOVEBHV(XFS_MTOVFS(mp), &mp->m_bhv);
struct vfs *vfsp = XFS_MTOVFS(mp);
bhv_remove_all_vfsops(vfsp, 0);
VFS_REMOVEBHV(vfsp, &mp->m_bhv);
}
spinlock_destroy(&mp->m_freeze_lock);
sv_destroy(&mp->m_wait_unfreeze);
kmem_free(mp, sizeof(xfs_mount_t));
......@@ -605,14 +599,11 @@ xfs_mountfs(
{
xfs_buf_t *bp;
xfs_sb_t *sbp = &(mp->m_sb);
int error = 0;
xfs_inode_t *rip;
vnode_t *rvp = 0;
int readio_log;
int writeio_log;
int readio_log, writeio_log;
vmap_t vmap;
xfs_daddr_t d;
extern xfs_ioops_t xfs_iocore_xfs; /* from xfs_iocore.c */
__uint64_t ret64;
uint quotaflags, quotaondisk;
uint uquotaondisk = 0, gquotaondisk = 0;
......@@ -620,6 +611,7 @@ xfs_mountfs(
__int64_t update_flags;
int agno, noio;
int uuid_mounted = 0;
int error = 0;
noio = dev == 0 && mp->m_sb_bp != NULL;
if (mp->m_sb_bp == NULL) {
......@@ -644,7 +636,8 @@ xfs_mountfs(
if ((BBTOB(mp->m_dalign) & mp->m_blockmask) ||
(BBTOB(mp->m_swidth) & mp->m_blockmask)) {
if (mp->m_flags & XFS_MOUNT_RETERR) {
cmn_err(CE_WARN, "XFS: alignment check 1 failed");
cmn_err(CE_WARN,
"XFS: alignment check 1 failed");
error = XFS_ERROR(EINVAL);
goto error1;
}
......@@ -664,7 +657,8 @@ xfs_mountfs(
mp->m_swidth = XFS_BB_TO_FSBT(mp, mp->m_swidth);
} else {
if (mp->m_flags & XFS_MOUNT_RETERR) {
cmn_err(CE_WARN, "XFS: alignment check 3 failed");
cmn_err(CE_WARN,
"XFS: alignment check 3 failed");
error = XFS_ERROR(EINVAL);
goto error1;
}
......@@ -718,7 +712,8 @@ xfs_mountfs(
* since a single partition filesystem is identical to a single
* partition volume/filesystem.
*/
if ((mfsi_flags & XFS_MFSI_SECOND) == 0 && (mp->m_flags & XFS_MOUNT_NOUUID) == 0) {
if ((mfsi_flags & XFS_MFSI_SECOND) == 0 &&
(mp->m_flags & XFS_MOUNT_NOUUID) == 0) {
if (xfs_uuid_mount(mp)) {
error = XFS_ERROR(EINVAL);
goto error1;
......@@ -859,9 +854,6 @@ xfs_mountfs(
return(0);
}
/* Initialize the I/O function vector with XFS functions */
mp->m_io_ops = xfs_iocore_xfs;
/*
* Copies the low order bits of the timestamp and the randomly
* set "sequence" number out of a UUID.
......@@ -1118,6 +1110,7 @@ xfs_mountfs(
int
xfs_unmountfs(xfs_mount_t *mp, struct cred *cr)
{
struct vfs *vfsp = XFS_MTOVFS(mp);
int ndquots;
#if defined(DEBUG) || defined(INDUCE_IO_ERROR)
int64_t fsid;
......@@ -1178,10 +1171,10 @@ xfs_unmountfs(xfs_mount_t *mp, struct cred *cr)
/*
* clear all error tags on this filesystem
*/
memcpy(&fsid, &(XFS_MTOVFS(mp)->vfs_fsid), sizeof(int64_t));
(void) xfs_errortag_clearall_umount(fsid, mp->m_fsname, 0);
memcpy(&fsid, &vfsp->vfs_fsid, sizeof(int64_t));
xfs_errortag_clearall_umount(fsid, mp->m_fsname, 0);
#endif
XFS_IODONE(vfsp);
xfs_mount_free(mp, 1);
return 0;
}
......
/*
* Copyright (c) 2000-2002 Silicon Graphics, Inc. All Rights Reserved.
* 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
......@@ -95,7 +95,7 @@ struct flid;
struct buf;
typedef int (*xfs_ioinit_t)(struct vfs *,
struct xfs_mount_args *, int *);
struct xfs_mount_args *, int);
typedef int (*xfs_bmapi_t)(struct xfs_trans *, void *,
xfs_fileoff_t, xfs_filblks_t, int,
xfs_fsblock_t *, xfs_extlen_t,
......@@ -187,11 +187,6 @@ typedef struct xfs_ioops {
(*(mp)->m_io_ops.xfs_iodone)(vfsp)
/*
* Prototypes and functions for the XFS realtime subsystem.
*/
typedef struct xfs_mount {
bhv_desc_t m_bhv; /* vfs xfs behavior */
xfs_tid_t m_tid; /* next unused tid for fs */
......@@ -324,8 +319,7 @@ typedef struct xfs_mount {
#define XFS_MOUNT_NOALIGN 0x00000080 /* turn off stripe alignment
allocations */
/* 0x00000100 -- currently unused */
#define XFS_MOUNT_REGISTERED 0x00000200 /* registered with cxfs master
cell logic */
/* 0x00000200 -- currently unused */
#define XFS_MOUNT_NORECOVERY 0x00000400 /* no recovery - dirty fs */
#define XFS_MOUNT_SHARED 0x00000800 /* shared mount */
#define XFS_MOUNT_DFLT_IOSIZE 0x00001000 /* set default i/o size */
......@@ -336,14 +330,6 @@ typedef struct xfs_mount {
* 32 bits in size */
#define XFS_MOUNT_NOLOGFLUSH 0x00010000
/*
* Flags for m_cxfstype
*/
#define XFS_CXFS_NOT 0x00000001 /* local mount */
#define XFS_CXFS_SERVER 0x00000002 /* we're the CXFS server */
#define XFS_CXFS_CLIENT 0x00000004 /* We're a CXFS client */
#define XFS_CXFS_REC_ENABLED 0x00000008 /* recovery is enabled */
#define XFS_FORCED_SHUTDOWN(mp) ((mp)->m_flags & XFS_MOUNT_FS_SHUTDOWN)
/*
......@@ -370,15 +356,17 @@ typedef struct xfs_mount {
#define XFS_WSYNC_READIO_LOG 15 /* 32K */
#define XFS_WSYNC_WRITEIO_LOG 14 /* 16K */
#define xfs_force_shutdown(m,f) VFS_FORCE_SHUTDOWN(XFS_MTOVFS(m),f)
#define xfs_force_shutdown(m,f) \
VFS_FORCE_SHUTDOWN((XFS_MTOVFS(m)), f, __FILE__, __LINE__)
/*
* Flags sent to xfs_force_shutdown.
*/
#define XFS_METADATA_IO_ERROR 0x1
#define XFS_LOG_IO_ERROR 0x2
#define XFS_FORCE_UMOUNT 0x4
#define XFS_CORRUPT_INCORE 0x8 /* corrupt in-memory data structures */
#define XFS_SHUTDOWN_REMOTE_REQ 0x10 /* shutdown came from remote cell */
#define XFS_CORRUPT_INCORE 0x8 /* Corrupt in-memory data structures */
#define XFS_SHUTDOWN_REMOTE_REQ 0x10 /* Shutdown came from remote cell */
/*
* xflags for xfs_syncsub
......@@ -388,9 +376,7 @@ typedef struct xfs_mount {
/*
* Flags for xfs_mountfs
*/
#define XFS_MFSI_SECOND 0x01 /* Is a cxfs secondary mount -- skip */
/* stuff which should only be done */
/* once. */
#define XFS_MFSI_SECOND 0x01 /* Secondary mount -- skip stuff */
#define XFS_MFSI_CLIENT 0x02 /* Is a client -- skip lots of stuff */
#define XFS_MFSI_NOUNLINK 0x08 /* Skip unlinked inode processing in */
/* log recovery */
......@@ -410,6 +396,13 @@ xfs_mount_t *xfs_bhvtom(bhv_desc_t *bdp);
#else
#define XFS_BHVTOM(bdp) ((xfs_mount_t *)BHV_PDATA(bdp))
#endif
#if XFS_WANT_FUNCS || (XFS_WANT_SPACE && XFSSO_XFS_VFSTOM)
xfs_mount_t *xfs_vfstom(vfs_t *vfs);
#define XFS_VFSTOM(vfs) xfs_vfstom(vfs)
#else
#define XFS_VFSTOM(vfs) \
(XFS_BHVTOM(bhv_lookup(VFS_BHVHEAD(vfs), &xfs_vfsops)))
#endif
/*
......@@ -447,7 +440,7 @@ static inline xfs_agblock_t XFS_DADDR_TO_AGBNO(xfs_mount_t *mp, xfs_daddr_t d)
*/
typedef struct xfs_mod_sb {
xfs_sb_field_t msb_field; /* Field to modify, see below */
int msb_delta; /* change to make to the specified field */
int msb_delta; /* Change to make to specified field */
} xfs_mod_sb_t;
#define XFS_MOUNT_ILOCK(mp) mutex_lock(&((mp)->m_ilock), PINOD)
......@@ -455,24 +448,26 @@ typedef struct xfs_mod_sb {
#define XFS_SB_LOCK(mp) mutex_spinlock(&(mp)->m_sb_lock)
#define XFS_SB_UNLOCK(mp,s) mutex_spinunlock(&(mp)->m_sb_lock,(s))
void xfs_mod_sb(xfs_trans_t *, __int64_t);
xfs_mount_t *xfs_mount_init(void);
void xfs_mount_free(xfs_mount_t *mp, int remove_bhv);
int xfs_mountfs(struct vfs *, xfs_mount_t *mp, dev_t, int);
int xfs_unmountfs(xfs_mount_t *, struct cred *);
void xfs_unmountfs_close(xfs_mount_t *, struct cred *);
int xfs_unmountfs_writesb(xfs_mount_t *);
int xfs_unmount_flush(xfs_mount_t *, int);
int xfs_mod_incore_sb(xfs_mount_t *, xfs_sb_field_t, int, int);
int xfs_mod_incore_sb_batch(xfs_mount_t *, xfs_mod_sb_t *, uint, int);
int xfs_readsb(xfs_mount_t *mp);
struct xfs_buf *xfs_getsb(xfs_mount_t *, int);
void xfs_freesb(xfs_mount_t *);
void xfs_do_force_shutdown(bhv_desc_t *, int, char *, int);
int xfs_syncsub(xfs_mount_t *, int, int, int *);
void xfs_initialize_perag(xfs_mount_t *, int);
void xfs_xlatesb(void *, struct xfs_sb *, int, xfs_arch_t, __int64_t);
extern xfs_mount_t *xfs_mount_init(void);
extern void xfs_mod_sb(xfs_trans_t *, __int64_t);
extern void xfs_mount_free(xfs_mount_t *mp, int remove_bhv);
extern int xfs_mountfs(struct vfs *, xfs_mount_t *mp, dev_t, int);
extern int xfs_unmountfs(xfs_mount_t *, struct cred *);
extern void xfs_unmountfs_close(xfs_mount_t *, struct cred *);
extern int xfs_unmountfs_writesb(xfs_mount_t *);
extern int xfs_unmount_flush(xfs_mount_t *, int);
extern int xfs_mod_incore_sb(xfs_mount_t *, xfs_sb_field_t, int, int);
extern int xfs_mod_incore_sb_batch(xfs_mount_t *, xfs_mod_sb_t *,
uint, int);
extern struct xfs_buf *xfs_getsb(xfs_mount_t *, int);
extern int xfs_readsb(xfs_mount_t *mp);
extern void xfs_freesb(xfs_mount_t *);
extern void xfs_do_force_shutdown(bhv_desc_t *, int, char *, int);
extern int xfs_syncsub(xfs_mount_t *, int, int, int *);
extern void xfs_initialize_perag(xfs_mount_t *, int);
extern void xfs_xlatesb(void *, struct xfs_sb *, int, xfs_arch_t,
__int64_t);
/*
* Flags for freeze operations.
......@@ -480,11 +475,20 @@ void xfs_xlatesb(void *, struct xfs_sb *, int, xfs_arch_t, __int64_t);
#define XFS_FREEZE_WRITE 1
#define XFS_FREEZE_TRANS 2
void xfs_start_freeze(xfs_mount_t *, int);
void xfs_finish_freeze(xfs_mount_t *);
void xfs_check_frozen(xfs_mount_t *, bhv_desc_t *, int);
extern void xfs_start_freeze(xfs_mount_t *, int);
extern void xfs_finish_freeze(xfs_mount_t *);
extern void xfs_check_frozen(xfs_mount_t *, bhv_desc_t *, int);
extern struct vfsops xfs_vfsops;
extern struct vnodeops xfs_vnodeops;
extern struct xfs_ioops xfs_iocore_xfs;
extern struct vfsops xfs_qmops_xfs;
extern struct vfsops xfs_dmops_xfs;
extern int xfs_init(void);
extern void xfs_cleanup(void);
#endif /* __KERNEL__ */
......
/*
* Copyright (c) 2000-2002 Silicon Graphics, Inc. All Rights Reserved.
* 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
......@@ -199,10 +199,7 @@ extern int xfs_qm_mplist_nowait(xfs_mount_t *);
extern int xfs_qm_dqhashlock_nowait(xfs_dquot_t *);
/* system call interface */
extern int linvfs_getxstate(struct super_block *, struct fs_quota_stat *);
extern int linvfs_setxstate(struct super_block *, unsigned int, int);
extern int linvfs_getxquota(struct super_block *, int, qid_t, struct fs_disk_quota *);
extern int linvfs_setxquota(struct super_block *, int, qid_t, struct fs_disk_quota *);
extern int xfs_qm_quotactl(bhv_desc_t *, int, int, xfs_caddr_t);
#ifdef DEBUG
extern int xfs_qm_internalqcheck(xfs_mount_t *);
......
/*
* Copyright (c) 2000-2002 Silicon Graphics, Inc. All Rights Reserved.
* 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
......@@ -34,7 +34,7 @@
#include <xfs_quota_priv.h>
#ifdef DEBUG
# define qdprintk(s, args...) printk(s, ## args)
# define qdprintk(s, args...) cmn_err(CE_DEBUG, s, ## args)
#else
# define qdprintk(s, args...) do { } while (0)
#endif
......@@ -58,95 +58,123 @@ STATIC void xfs_qm_export_dquot(xfs_mount_t *, xfs_disk_dquot_t *,
fs_disk_quota_t *);
/*
* The main distribution switch of all XFS quotactl system calls.
*/
int
linvfs_getxstate(
struct super_block *sb,
struct fs_quota_stat *fqs)
xfs_qm_quotactl(
struct bhv_desc *bdp,
int cmd,
int id,
xfs_caddr_t addr)
{
xfs_mount_t *mp;
vfs_t *vfsp;
int error;
struct vfs *vfsp;
vfsp = LINVFS_GET_VFS(sb);
mp = XFS_BHVTOM(vfsp->vfs_fbhv);
return -xfs_qm_scall_getqstat(mp, fqs);
}
vfsp = bhvtovfs(bdp);
mp = XFS_VFSTOM(vfsp);
int
linvfs_setxstate(
struct super_block *sb,
unsigned int flags,
int op)
{
xfs_mount_t *mp;
vfs_t *vfsp;
uint qflags;
if (addr == NULL && cmd != Q_SYNC)
return XFS_ERROR(EINVAL);
if (id < 0 && cmd != Q_SYNC)
return XFS_ERROR(EINVAL);
vfsp = LINVFS_GET_VFS(sb);
mp = XFS_BHVTOM(vfsp->vfs_fbhv);
/*
* The following commands are valid even when quotaoff.
*/
switch (cmd) {
/*
* truncate quota files. quota must be off.
*/
case Q_XQUOTARM:
if (XFS_IS_QUOTA_ON(mp) || addr == NULL)
return XFS_ERROR(EINVAL);
if (vfsp->vfs_flag & VFS_RDONLY)
return -EROFS;
return XFS_ERROR(EROFS);
return (xfs_qm_scall_trunc_qfiles(mp,
xfs_qm_import_qtype_flags(*(uint *)addr)));
/*
* Get quota status information.
*/
case Q_XGETQSTAT:
return (xfs_qm_scall_getqstat(mp, (fs_quota_stat_t *)addr));
switch (op) {
case Q_XQUOTARM:
if (XFS_IS_QUOTA_ON(mp)) {
qdprintk("cannot remove, quota on: flags=%x\n", flags);
return -EINVAL;
}
qflags = xfs_qm_import_qtype_flags(flags);
return -xfs_qm_scall_trunc_qfiles(mp, qflags);
/*
* QUOTAON for root f/s and quota enforcement on others..
* Quota accounting for non-root f/s's must be turned on
* at mount time.
*/
case Q_XQUOTAON:
qflags = xfs_qm_import_flags(flags);
return -xfs_qm_scall_quotaon(mp, qflags);
if (addr == NULL)
return XFS_ERROR(EINVAL);
if (vfsp->vfs_flag & VFS_RDONLY)
return XFS_ERROR(EROFS);
return (xfs_qm_scall_quotaon(mp,
xfs_qm_import_flags(*(uint *)addr)));
case Q_XQUOTAOFF:
qflags = xfs_qm_import_flags(flags);
if (!XFS_IS_QUOTA_ON(mp))
return -ESRCH;
return -xfs_qm_scall_quotaoff(mp, qflags, B_FALSE);
if (vfsp->vfs_flag & VFS_RDONLY)
return XFS_ERROR(EROFS);
break;
default:
break;
}
qdprintk("cannot set state, invalid op: op=%x flags=%x\n", op, flags);
return -EINVAL;
}
int
linvfs_getxquota(
struct super_block *sb,
int type,
qid_t id,
struct fs_disk_quota *fdq)
{
xfs_mount_t *mp;
vfs_t *vfsp;
int qtype;
vfsp = LINVFS_GET_VFS(sb);
mp = XFS_BHVTOM(vfsp->vfs_fbhv);
if (!XFS_IS_QUOTA_ON(mp))
return -ESRCH;
qtype = (type == GRPQUOTA)? XFS_DQ_GROUP : XFS_DQ_USER;
return -xfs_qm_scall_getquota(mp, (xfs_dqid_t)id, qtype, fdq);
}
if (! XFS_IS_QUOTA_ON(mp))
return XFS_ERROR(ESRCH);
int
linvfs_setxquota(
struct super_block *sb,
int type,
qid_t id,
struct fs_disk_quota *fdq)
{
xfs_mount_t *mp;
vfs_t *vfsp;
int qtype;
switch (cmd) {
case Q_XQUOTAOFF:
if (vfsp->vfs_flag & VFS_RDONLY)
return XFS_ERROR(EROFS);
error = xfs_qm_scall_quotaoff(mp,
xfs_qm_import_flags(*(uint *)addr),
B_FALSE);
break;
vfsp = LINVFS_GET_VFS(sb);
mp = XFS_BHVTOM(vfsp->vfs_fbhv);
if (!XFS_IS_QUOTA_ON(mp))
return -ESRCH;
/*
* Defaults to XFS_GETUQUOTA.
*/
case Q_XGETQUOTA:
error = xfs_qm_scall_getquota(mp, (xfs_dqid_t)id, XFS_DQ_USER,
(fs_disk_quota_t *)addr);
break;
/*
* Set limits, both hard and soft. Defaults to Q_SETUQLIM.
*/
case Q_XSETQLIM:
if (vfsp->vfs_flag & VFS_RDONLY)
return -EROFS;
qtype = (type == GRPQUOTA)? XFS_DQ_GROUP : XFS_DQ_USER;
return xfs_qm_scall_setqlim(mp, (xfs_dqid_t)id, qtype, fdq);
}
return XFS_ERROR(EROFS);
error = xfs_qm_scall_setqlim(mp, (xfs_dqid_t)id, XFS_DQ_USER,
(fs_disk_quota_t *)addr);
break;
case Q_XSETGQLIM:
if (vfsp->vfs_flag & VFS_RDONLY)
return XFS_ERROR(EROFS);
error = xfs_qm_scall_setqlim(mp, (xfs_dqid_t)id, XFS_DQ_GROUP,
(fs_disk_quota_t *)addr);
break;
case Q_XGETGQUOTA:
error = xfs_qm_scall_getquota(mp, (xfs_dqid_t)id, XFS_DQ_GROUP,
(fs_disk_quota_t *)addr);
break;
/*
* Quotas are entirely undefined after quotaoff in XFS quotas.
* For instance, there's no way to set limits when quotaoff.
*/
default:
error = XFS_ERROR(EINVAL);
break;
}
return (error);
}
/*
* Turn off quota accounting and/or enforcement for all udquots and/or
......@@ -487,6 +515,7 @@ xfs_qm_scall_getqstat(
out->qs_pad = 0;
out->qs_uquota.qfs_ino = mp->m_sb.sb_uquotino;
out->qs_gquota.qfs_ino = mp->m_sb.sb_gquotino;
if (mp->m_quotainfo) {
uip = mp->m_quotainfo->qi_uquotaip;
gip = mp->m_quotainfo->qi_gquotaip;
......@@ -1048,10 +1077,10 @@ mutex_t qcheck_lock;
#define DQTEST_LIST_PRINT(l, NXT, title) \
{ \
xfs_dqtest_t *dqp; int i = 0;\
printk("%s (#%d)\n", title, (int) (l)->qh_nelems); \
cmn_err(CE_DEBUG, "%s (#%d)", title, (int) (l)->qh_nelems); \
for (dqp = (xfs_dqtest_t *)(l)->qh_next; dqp != NULL; \
dqp = (xfs_dqtest_t *)dqp->NXT) { \
printk("\t%d\.\t\"%d (%s)\"\t bcnt = %d, icnt = %d\n", \
cmn_err(CE_DEBUG, " %d\. \"%d (%s)\" bcnt = %d, icnt = %d", \
++i, dqp->d_id, DQFLAGTO_TYPESTR(dqp), \
dqp->d_bcount, dqp->d_icount); } \
}
......@@ -1081,13 +1110,15 @@ STATIC void
xfs_qm_dqtest_print(
xfs_dqtest_t *d)
{
printk("-----------DQTEST DQUOT----------------\n");
printk("---- dquot ID = %d\n", d->d_id);
printk("---- type = %s\n", XFS_QM_ISUDQ(d) ? "USR" : "GRP");
printk("---- fs = 0x%p\n", d->q_mount);
printk("---- bcount = %Lu (0x%x)\n", d->d_bcount, (int)d->d_bcount);
printk("---- icount = %Lu (0x%x)\n", d->d_icount, (int)d->d_icount);
printk("---------------------------\n");
cmn_err(CE_DEBUG, "-----------DQTEST DQUOT----------------");
cmn_err(CE_DEBUG, "---- dquot ID = %d", d->d_id);
cmn_err(CE_DEBUG, "---- type = %s", XFS_QM_ISUDQ(d)? "USR" : "GRP");
cmn_err(CE_DEBUG, "---- fs = 0x%p", d->q_mount);
cmn_err(CE_DEBUG, "---- bcount = %Lu (0x%x)",
d->d_bcount, (int)d->d_bcount);
cmn_err(CE_DEBUG, "---- icount = %Lu (0x%x)",
d->d_icount, (int)d->d_icount);
cmn_err(CE_DEBUG, "---------------------------");
}
STATIC void
......@@ -1101,10 +1132,10 @@ xfs_qm_dqtest_failed(
{
qmtest_nfails++;
if (error)
printk("quotacheck failed for %d, error = %d\nreason = %s\n",
cmn_err(CE_DEBUG, "quotacheck failed id=%d, err=%d\nreason: %s",
INT_GET(d->d_id, ARCH_CONVERT), error, reason);
else
printk("quotacheck failed for %d (%s) [%d != %d]\n",
cmn_err(CE_DEBUG, "quotacheck failed id=%d (%s) [%d != %d]",
INT_GET(d->d_id, ARCH_CONVERT), reason, (int)a, (int)b);
xfs_qm_dqtest_print(d);
if (dqp)
......@@ -1119,35 +1150,41 @@ xfs_dqtest_cmp2(
int err = 0;
if (INT_GET(dqp->q_core.d_icount, ARCH_CONVERT) != d->d_icount) {
xfs_qm_dqtest_failed(d, dqp, "icount mismatch",
INT_GET(dqp->q_core.d_icount, ARCH_CONVERT), d->d_icount, 0);
INT_GET(dqp->q_core.d_icount, ARCH_CONVERT),
d->d_icount, 0);
err++;
}
if (INT_GET(dqp->q_core.d_bcount, ARCH_CONVERT) != d->d_bcount) {
xfs_qm_dqtest_failed(d, dqp, "bcount mismatch",
INT_GET(dqp->q_core.d_bcount, ARCH_CONVERT), d->d_bcount, 0);
INT_GET(dqp->q_core.d_bcount, ARCH_CONVERT),
d->d_bcount, 0);
err++;
}
if (INT_GET(dqp->q_core.d_blk_softlimit, ARCH_CONVERT) &&
INT_GET(dqp->q_core.d_bcount, ARCH_CONVERT) >= INT_GET(dqp->q_core.d_blk_softlimit, ARCH_CONVERT)) {
INT_GET(dqp->q_core.d_bcount, ARCH_CONVERT) >=
INT_GET(dqp->q_core.d_blk_softlimit, ARCH_CONVERT)) {
if (INT_ISZERO(dqp->q_core.d_btimer, ARCH_CONVERT) &&
!INT_ISZERO(dqp->q_core.d_id, ARCH_CONVERT)) {
printk("%d [%s] [0x%p] BLK TIMER NOT STARTED\n",
cmn_err(CE_DEBUG,
"%d [%s] [0x%p] BLK TIMER NOT STARTED",
d->d_id, DQFLAGTO_TYPESTR(d), d->q_mount);
err++;
}
}
if (INT_GET(dqp->q_core.d_ino_softlimit, ARCH_CONVERT) &&
INT_GET(dqp->q_core.d_icount, ARCH_CONVERT) >= INT_GET(dqp->q_core.d_ino_softlimit, ARCH_CONVERT)) {
INT_GET(dqp->q_core.d_icount, ARCH_CONVERT) >=
INT_GET(dqp->q_core.d_ino_softlimit, ARCH_CONVERT)) {
if (INT_ISZERO(dqp->q_core.d_itimer, ARCH_CONVERT) &&
!INT_ISZERO(dqp->q_core.d_id, ARCH_CONVERT)) {
printk("%d [%s] [0x%p] INO TIMER NOT STARTED\n",
cmn_err(CE_DEBUG,
"%d [%s] [0x%p] INO TIMER NOT STARTED",
d->d_id, DQFLAGTO_TYPESTR(d), d->q_mount);
err++;
}
}
#if 0
#ifdef QUOTADEBUG
if (!err) {
printk("%d [%s] [0x%p] qchecked\n",
cmn_err(CE_DEBUG, "%d [%s] [0x%p] qchecked",
d->d_id, XFS_QM_ISUDQ(d) ? "USR" : "GRP", d->q_mount);
}
#endif
......@@ -1338,10 +1375,9 @@ xfs_qm_internalqcheck(
}
} while (! done);
if (error) {
printk("Bulkstat returned error 0x%x\n",
error);
cmn_err(CE_DEBUG, "Bulkstat returned error 0x%x", error);
}
printk("Checking results against system dquots\n");
cmn_err(CE_DEBUG, "Checking results against system dquots");
for (i = 0; i < qmtest_hashmask; i++) {
h1 = &qmtest_udqtab[i];
for (d = (xfs_dqtest_t *) h1->qh_next; d != NULL; ) {
......@@ -1360,10 +1396,10 @@ xfs_qm_internalqcheck(
}
if (qmtest_nfails) {
printk("************** quotacheck failed **************\n");
printk("failures = %d\n", qmtest_nfails);
cmn_err(CE_DEBUG, "******** quotacheck failed ********");
cmn_err(CE_DEBUG, "failures = %d", qmtest_nfails);
} else {
printk("************** quotacheck successful! **************\n");
cmn_err(CE_DEBUG, "******** quotacheck successful! ********");
}
kmem_free(qmtest_udqtab, qmtest_hashmask * sizeof(xfs_dqhash_t));
kmem_free(qmtest_gdqtab, qmtest_hashmask * sizeof(xfs_dqhash_t));
......
/*
* 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>
#define MNTOPT_QUOTA "quota" /* disk quotas (user) */
#define MNTOPT_NOQUOTA "noquota" /* no quotas */
#define MNTOPT_USRQUOTA "usrquota" /* user quota enabled */
#define MNTOPT_GRPQUOTA "grpquota" /* group quota enabled */
#define MNTOPT_UQUOTA "uquota" /* user quota (IRIX variant) */
#define MNTOPT_GQUOTA "gquota" /* group quota (IRIX variant) */
#define MNTOPT_UQUOTANOENF "uqnoenforce"/* user quota limit enforcement */
#define MNTOPT_GQUOTANOENF "gqnoenforce"/* group quota limit enforcement */
#define MNTOPT_QUOTANOENF "qnoenforce" /* same as uqnoenforce */
STATIC int
xfs_qm_parseargs(
struct bhv_desc *bhv,
char *options,
struct xfs_mount_args *args,
int update)
{
size_t length;
char *local_options = options;
char *this_char;
int error;
int referenced = update;
while ((this_char = strsep(&local_options, ",")) != NULL) {
length = strlen(this_char);
if (local_options)
length++;
if (!strcmp(this_char, MNTOPT_NOQUOTA)) {
args->flags &= ~(XFSMNT_UQUOTAENF|XFSMNT_UQUOTA);
args->flags &= ~(XFSMNT_GQUOTAENF|XFSMNT_GQUOTA);
referenced = update;
} else if (!strcmp(this_char, MNTOPT_QUOTA) ||
!strcmp(this_char, MNTOPT_UQUOTA) ||
!strcmp(this_char, MNTOPT_USRQUOTA)) {
args->flags |= XFSMNT_UQUOTA | XFSMNT_UQUOTAENF;
referenced = 1;
} else if (!strcmp(this_char, MNTOPT_QUOTANOENF) ||
!strcmp(this_char, MNTOPT_UQUOTANOENF)) {
args->flags |= XFSMNT_UQUOTA;
args->flags &= ~XFSMNT_UQUOTAENF;
referenced = 1;
} else if (!strcmp(this_char, MNTOPT_GQUOTA) ||
!strcmp(this_char, MNTOPT_GRPQUOTA)) {
args->flags |= XFSMNT_GQUOTA | XFSMNT_GQUOTAENF;
referenced = 1;
} else if (!strcmp(this_char, MNTOPT_GQUOTANOENF)) {
args->flags |= XFSMNT_GQUOTA;
args->flags &= ~XFSMNT_GQUOTAENF;
referenced = 1;
} else {
if (local_options)
*(local_options-1) = ',';
continue;
}
while (length--)
*this_char++ = ',';
}
PVFS_PARSEARGS(BHV_NEXT(bhv), options, args, update, error);
if (!error && !referenced)
bhv_remove_vfsops(bhvtovfs(bhv), VFS_POSITION_QM);
return error;
}
STATIC int
xfs_qm_showargs(
struct bhv_desc *bhv,
struct seq_file *m)
{
struct vfs *vfsp = bhvtovfs(bhv);
struct xfs_mount *mp = XFS_VFSTOM(vfsp);
int error;
if (mp->m_qflags & XFS_UQUOTA_ACCT) {
(mp->m_qflags & XFS_UQUOTA_ENFD) ?
seq_puts(m, "," MNTOPT_UQUOTA) :
seq_puts(m, "," MNTOPT_UQUOTANOENF);
}
if (mp->m_qflags & XFS_GQUOTA_ACCT) {
(mp->m_qflags & XFS_GQUOTA_ENFD) ?
seq_puts(m, "," MNTOPT_GQUOTA) :
seq_puts(m, "," MNTOPT_GQUOTANOENF);
}
if (!(mp->m_qflags & (XFS_UQUOTA_ACCT|XFS_GQUOTA_ACCT)))
seq_puts(m, "," MNTOPT_NOQUOTA);
PVFS_SHOWARGS(BHV_NEXT(bhv), m, error);
return error;
}
STATIC int
xfs_qm_mount(
struct bhv_desc *bhv,
struct xfs_mount_args *args,
struct cred *cr)
{
struct vfs *vfsp = bhvtovfs(bhv);
struct xfs_mount *mp = XFS_VFSTOM(vfsp);
int error;
if (args->flags & (XFSMNT_UQUOTA | XFSMNT_GQUOTA))
xfs_qm_mount_quotainit(mp, args->flags);
PVFS_MOUNT(BHV_NEXT(bhv), args, cr, error);
return error;
}
STATIC int
xfs_qm_syncall(
struct bhv_desc *bhv,
int flags,
cred_t *credp)
{
struct vfs *vfsp = bhvtovfs(bhv);
struct xfs_mount *mp = XFS_VFSTOM(vfsp);
int error;
/*
* Get the Quota Manager to flush the dquots.
*/
if (XFS_IS_QUOTA_ON(mp)) {
if ((error = xfs_qm_sync(mp, flags))) {
/*
* If we got an IO error, we will be shutting down.
* So, there's nothing more for us to do here.
*/
ASSERT(error != EIO || XFS_FORCED_SHUTDOWN(mp));
if (XFS_FORCED_SHUTDOWN(mp)) {
return XFS_ERROR(error);
}
}
}
PVFS_SYNC(BHV_NEXT(bhv), flags, credp, error);
return error;
}
vfsops_t xfs_qmops_xfs = {
BHV_IDENTITY_INIT(VFS_BHV_QM, VFS_POSITION_QM),
.vfs_parseargs = xfs_qm_parseargs,
.vfs_showargs = xfs_qm_showargs,
.vfs_mount = xfs_qm_mount,
.vfs_sync = xfs_qm_syncall,
.vfs_quotactl = xfs_qm_quotactl,
};
/*
* XFS filesystem operations.
*
* Copyright (c) 2000-2002 Silicon Graphics, Inc. All Rights Reserved.
* 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
......@@ -248,9 +248,6 @@ xfs_start_flags(
if (ap->flags & XFSMNT_NOATIME)
mp->m_flags |= XFS_MOUNT_NOATIME;
if (ap->flags & (XFSMNT_UQUOTA | XFSMNT_GQUOTA))
xfs_qm_mount_quotainit(mp, ap->flags);
if (ap->flags & XFSMNT_RETERR)
mp->m_flags |= XFS_MOUNT_RETERR;
......@@ -387,11 +384,12 @@ xfs_finish_flags(
*/
STATIC int
xfs_mount(
vfs_t *vfsp,
struct bhv_desc *bhvp,
struct xfs_mount_args *args,
cred_t *credp)
{
xfs_mount_t *mp;
struct vfs *vfsp = bhvtovfs(bhvp);
struct xfs_mount *mp = XFS_BHVTOM(bhvp);
struct block_device *ddev, *logdev, *rtdev;
int ronly = (vfsp->vfs_flag & VFS_RDONLY);
int flags = 0, error;
......@@ -399,24 +397,19 @@ xfs_mount(
ddev = vfsp->vfs_super->s_bdev;
logdev = rtdev = NULL;
/*
* Allocate VFS private data (xfs mount structure).
*/
mp = xfs_mount_init();
/*
* Open real time and log devices - order is important.
*/
if (args->logname[0]) {
error = xfs_blkdev_get(mp, args->logname, &logdev);
if (error)
goto free_mp;
return error;
}
if (args->rtname[0]) {
error = xfs_blkdev_get(mp, args->rtname, &rtdev);
if (error) {
xfs_blkdev_put(logdev);
goto free_mp;
return error;
}
if (rtdev == ddev || rtdev == logdev) {
......@@ -424,12 +417,11 @@ xfs_mount(
"XFS: Cannot mount filesystem with identical rtdev and ddev/logdev.");
xfs_blkdev_put(logdev);
xfs_blkdev_put(rtdev);
error = EINVAL;
goto free_mp;
return EINVAL;
}
}
vfs_insertbhv(vfsp, &mp->m_bhv, &xfs_vfsops, mp);
mp->m_io_ops = xfs_iocore_xfs;
mp->m_ddev_targp = xfs_alloc_buftarg(ddev);
if (rtdev)
......@@ -465,9 +457,7 @@ xfs_mount(
xfs_setsize_buftarg(mp->m_rtdev_targp, mp->m_sb.sb_blocksize,
mp->m_sb.sb_blocksize);
error = xfs_mountfs(vfsp, mp, ddev->bd_dev, flags);
if (error)
goto error;
if (!(error = XFS_IOINIT(vfsp, args, flags)))
return 0;
error:
......@@ -479,9 +469,6 @@ xfs_mount(
xfs_binval(mp->m_rtdev_targp);
}
xfs_unmountfs_close(mp, NULL);
free_mp:
xfs_mount_free(mp, 1);
return error;
}
......@@ -523,8 +510,9 @@ xfs_ibusy(
continue;
}
#ifdef DEBUG
printk("busy vp=0x%p ip=0x%p inum %Ld count=%d\n",
vp, ip, ip->i_ino, vn_count(vp));
cmn_err(CE_WARN, "%s: busy vp=0x%p ip=0x%p "
"inum %Ld count=%d",
__FUNCTION__, vp, ip, ip->i_ino, vn_count(vp));
#endif
busy++;
}
......@@ -577,7 +565,8 @@ xfs_unmount(
*/
if (xfs_ibusy(mp)) {
error = XFS_ERROR(EBUSY);
printk("xfs_unmount: xfs_ibusy says error/%d\n", error);
cmn_err(CE_ALERT, "%s: xfs_ibusy failed -- error code %d",
__FUNCTION__, error);
goto out;
}
......@@ -641,7 +630,7 @@ xfs_unmount_flush(
{
xfs_inode_t *rip = mp->m_rootip;
xfs_inode_t *rbmip;
xfs_inode_t *rsumip=NULL;
xfs_inode_t *rsumip = NULL;
vnode_t *rvp = XFS_ITOV(rip);
int error;
......@@ -675,18 +664,17 @@ xfs_unmount_flush(
}
/*
* synchronously flush root inode to disk
* Synchronously flush root inode to disk
*/
error = xfs_iflush(rip, XFS_IFLUSH_SYNC);
if (error == EFSCORRUPTED)
goto fscorrupt_out2;
if (vn_count(rvp) != 1 && !relocation) {
xfs_iunlock(rip, XFS_ILOCK_EXCL);
error = XFS_ERROR(EBUSY);
return (error);
return XFS_ERROR(EBUSY);
}
/*
* Release dquot that rootinode, rbmino and rsumino might be holding,
* flush and purge the quota inodes.
......@@ -701,7 +689,7 @@ xfs_unmount_flush(
}
xfs_iunlock(rip, XFS_ILOCK_EXCL);
return (0);
return 0;
fscorrupt_out:
xfs_ifunlock(rip);
......@@ -709,8 +697,7 @@ xfs_unmount_flush(
fscorrupt_out2:
xfs_iunlock(rip, XFS_ILOCK_EXCL);
error = XFS_ERROR(EFSCORRUPTED);
return (error);
return XFS_ERROR(EFSCORRUPTED);
}
/*
......@@ -730,7 +717,6 @@ xfs_root(
vp = XFS_ITOV((XFS_BHVTOM(bdp))->m_rootip);
VN_HOLD(vp);
*vpp = vp;
return 0;
}
......@@ -1410,23 +1396,6 @@ xfs_syncsub(
ASSERT(ipointer_in == B_FALSE);
/*
* Get the Quota Manager to flush the dquots in a similar manner.
*/
if (XFS_IS_QUOTA_ON(mp)) {
if ((error = xfs_qm_sync(mp, flags))) {
/*
* If we got an IO error, we will be shutting down.
* So, there's nothing more for us to do here.
*/
ASSERT(error != EIO || XFS_FORCED_SHUTDOWN(mp));
if (XFS_FORCED_SHUTDOWN(mp)) {
kmem_free(ipointer, sizeof(xfs_iptr_t));
return XFS_ERROR(error);
}
}
}
/*
* Flushing out dirty data above probably generated more
* log activity, so if this isn't vfs_sync() then flush
......@@ -1581,16 +1550,17 @@ xfs_vget(
vfsops_t xfs_vfsops = {
BHV_IDENTITY_INIT(VFS_BHV_XFS,VFS_POSITION_XFS),
.vfs_parseargs = xfs_parseargs,
.vfs_showargs = xfs_showargs,
.vfs_mount = xfs_mount,
.vfs_unmount = xfs_unmount,
.vfs_root = xfs_root,
.vfs_statvfs = xfs_statvfs,
.vfs_sync = xfs_sync,
.vfs_vget = xfs_vget,
.vfs_dmapiops = (vfs_dmapiops_t)fs_nosys,
.vfs_quotactl = (vfs_quotactl_t)fs_nosys,
.vfs_init_vnode = xfs_initialize_vnode,
.vfs_force_shutdown = xfs_do_force_shutdown,
#ifdef CONFIG_XFS_DMAPI
.vfs_dmapi_mount = xfs_dm_mount,
.vfs_dmapi_fsys_vector = xfs_dm_get_fsys_vector,
#endif
};
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment