Commit 04792016 authored by Christoph Hellwig's avatar Christoph Hellwig

Merge

parents 5ec5104a fec5b075
#
# 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
......@@ -29,13 +29,7 @@
#
# http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
#
# 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)
......@@ -48,17 +42,22 @@ endif
obj-$(CONFIG_XFS_FS) += xfs.o
xfs-$(CONFIG_XFS_RT) += xfs_rtalloc.o
xfs-$(CONFIG_XFS_QUOTA) += xfs_dquot.o \
xfs-$(CONFIG_XFS_QUOTA) += $(addprefix quota/, \
xfs_dquot.o \
xfs_dquot_item.o \
xfs_trans_dquot.o \
xfs_qm_syscalls.o \
xfs_qm.o
xfs_qm_bhv.o \
xfs_qm.o)
ifeq ($(CONFIG_XFS_QUOTA),y)
xfs-$(CONFIG_PROC_FS) += quota/xfs_qm_stats.o
endif
xfs-$(CONFIG_XFS_RT) += xfs_rtalloc.o
xfs-$(CONFIG_XFS_POSIX_ACL) += xfs_acl.o
xfs-$(CONFIG_FS_POSIX_CAP) += xfs_cap.o
xfs-$(CONFIG_FS_POSIX_MAC) += xfs_mac.o
xfs-$(CONFIG_XFS_POSIX_CAP) += xfs_cap.o
xfs-$(CONFIG_XFS_POSIX_MAC) += xfs_mac.o
xfs-$(CONFIG_PROC_FS) += linux/xfs_stats.o
xfs-$(CONFIG_SYSCTL) += linux/xfs_sysctl.o
......@@ -127,6 +126,7 @@ xfs-y += $(addprefix linux/, \
xfs_iops.o \
xfs_lrw.o \
xfs_super.o \
xfs_vfs.o \
xfs_vnode.o)
# Objects in support/
......@@ -139,6 +139,10 @@ xfs-y += $(addprefix support/, \
qsort.o \
uuid.o)
# Quota and DMAPI stubs
xfs-y += xfs_dmops.o \
xfs_qmops.o
# If both xfs and kdb modules are built in then xfsidbg is built in. If xfs is
# a module and kdb modules are being compiled then xfsidbg must be a module, to
# follow xfs. If xfs is built in then xfsidbg tracks the kdb module state.
......
......@@ -78,6 +78,7 @@ xfs_unwritten_conv(
XFS_BUF_OFFSET(bp), XFS_BUF_SIZE(bp));
XFS_BUF_SET_FSPRIVATE(bp, NULL);
XFS_BUF_CLR_IODONE_FUNC(bp);
XFS_BUF_UNDATAIO(bp);
xfs_biodone(bp);
}
......@@ -431,6 +432,7 @@ map_unwritten(
size = nblocks; /* NB: using 64bit number here */
size <<= block_bits; /* convert fsb's to byte range */
XFS_BUF_DATAIO(pb);
XFS_BUF_SET_SIZE(pb, size);
XFS_BUF_SET_OFFSET(pb, offset);
XFS_BUF_SET_FSPRIVATE(pb, LINVFS_GET_VP(inode)->v_fbhv);
......
/*
* 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
......@@ -91,8 +91,8 @@
* active object
*
*/
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__ */
......@@ -299,7 +299,9 @@ linvfs_file_mmap(
int error;
if ((vp->v_type == VREG) && (vp->v_vfsp->vfs_flag & VFS_DMI)) {
error = -xfs_dm_send_mmap_event(vma, 0);
xfs_mount_t *mp = XFS_VFSTOM(vp->v_vfsp);
error = -XFS_SEND_MMAP(mp, vma, 0);
if (error)
return error;
}
......@@ -345,8 +347,10 @@ linvfs_mprotect(
if ((vp->v_type == VREG) && (vp->v_vfsp->vfs_flag & VFS_DMI)) {
if ((vma->vm_flags & VM_MAYSHARE) &&
(newflags & PROT_WRITE) && !(vma->vm_flags & PROT_WRITE)){
error = xfs_dm_send_mmap_event(vma, VM_WRITE);
(newflags & PROT_WRITE) && !(vma->vm_flags & PROT_WRITE)) {
xfs_mount_t *mp = XFS_VFSTOM(vp->v_vfsp);
error = XFS_SEND_MMAP(mp, vma, VM_WRITE);
}
}
return error;
......
/*
* 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,7 +40,7 @@
/*
* System memory size - used to scale certain data structures in XFS.
*/
unsigned long xfs_physmem;
unsigned long xfs_physmem;
/*
* Tunable XFS parameters. xfs_params is required even when CONFIG_SYSCTL=n,
......@@ -51,24 +51,14 @@ xfs_param_t xfs_params = { 0, 1, 0, 0, 0, 3 };
/*
* Used to serialize atomicIncWithWrap.
*/
spinlock_t Atomic_spin = SPIN_LOCK_UNLOCKED;
spinlock_t xfs_atomic_spin = SPIN_LOCK_UNLOCKED;
/*
* Global system credential structure.
*/
cred_t sys_cred_val, *sys_cred = &sys_cred_val;
/*
* The global quota manager. There is only one of these for the entire
* system, _not_ one per file system. XQM keeps track of the overall
* quota functionality, including maintaining the freelist and hash
* tables of dquots.
*/
struct xfs_qm *xfs_Gqm;
mutex_t xfs_Gqm_lock;
/* Export XFS symbols used by xfsidbg */
EXPORT_SYMBOL(xfs_Gqm);
EXPORT_SYMBOL(xfs_next_bit);
EXPORT_SYMBOL(xfs_contig_bits);
EXPORT_SYMBOL(xfs_bmbt_get_all);
......
/*
* 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
......@@ -39,11 +39,10 @@
extern uint64_t xfs_panic_mask; /* set to cause more panics */
extern unsigned long xfs_physmem;
extern unsigned long xfs_physmem;
extern struct cred *sys_cred;
extern spinlock_t xfs_atomic_spin;
extern struct xfs_qm *xfs_Gqm;
extern mutex_t xfs_Gqm_lock;
extern struct cred *sys_cred;
#endif /* __XFS_GLOBALS_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);
......
......@@ -258,11 +258,10 @@ xfs_iomap_write_direct(
* the ilock across a disk read.
*/
if (XFS_IS_QUOTA_ON(mp) && XFS_NOT_DQATTACHED(mp, ip)) {
if ((error = xfs_qm_dqattach(ip, XFS_QMOPT_ILOCKED))) {
return XFS_ERROR(error);
}
}
error = XFS_QM_DQATTACH(ip->i_mount, ip, XFS_QMOPT_ILOCKED);
if (error)
return XFS_ERROR(error);
maps = min(XFS_WRITE_IMAPS, *nmaps);
nimaps = maps;
......@@ -291,7 +290,7 @@ xfs_iomap_write_direct(
* determine if reserving space on
* the data or realtime partition.
*/
if ((rt = ip->i_d.di_flags & XFS_DIFLAG_REALTIME)) {
if ((rt = XFS_IS_REALTIME_INODE(ip))) {
int sbrtextsize, iprtextsize;
sbrtextsize = mp->m_sb.sb_rextsize;
......@@ -333,11 +332,9 @@ xfs_iomap_write_direct(
goto error_out; /* Don't return in above if .. trans ..,
need lock to return */
if (XFS_IS_QUOTA_ON(mp)) {
if (xfs_trans_reserve_blkquota(tp, ip, resblks)) {
error = (EDQUOT);
goto error1;
}
if (XFS_TRANS_RESERVE_BLKQUOTA(mp, tp, ip, resblks)) {
error = (EDQUOT);
goto error1;
}
nimaps = 1;
......@@ -422,11 +419,9 @@ xfs_iomap_write_delay(
* the ilock across a disk read.
*/
if (XFS_IS_QUOTA_ON(mp) && XFS_NOT_DQATTACHED(mp, ip)) {
if ((error = xfs_qm_dqattach(ip, XFS_QMOPT_ILOCKED))) {
return XFS_ERROR(error);
}
}
error = XFS_QM_DQATTACH(mp, ip, XFS_QMOPT_ILOCKED);
if (error)
return XFS_ERROR(error);
retry:
isize = ip->i_d.di_size;
......@@ -538,11 +533,8 @@ xfs_iomap_write_allocate(
* Make sure that the dquots are there.
*/
if (XFS_IS_QUOTA_ON(mp) && XFS_NOT_DQATTACHED(mp, ip)) {
if ((error = xfs_qm_dqattach(ip, 0))) {
return XFS_ERROR(error);
}
}
if ((error = XFS_QM_DQATTACH(mp, ip, 0)))
return XFS_ERROR(error);
offset_fsb = map->br_startoff;
count_fsb = map->br_blockcount;
......
/*
* 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 */
......
......@@ -121,7 +121,8 @@ xfs_read(
xfs_mount_t *mp;
vnode_t *vp;
unsigned long seg;
int direct = filp->f_flags & O_DIRECT;
int direct = (filp->f_flags & O_DIRECT);
int invisible = (filp->f_mode & FINVIS);
ip = XFS_BHVTOI(bdp);
vp = BHV_TO_VNODE(bdp);
......@@ -180,13 +181,12 @@ xfs_read(
xfs_ilock(ip, XFS_IOLOCK_SHARED);
if (DM_EVENT_ENABLED(vp->v_vfsp, ip, DM_EVENT_READ) &&
!(filp->f_mode & FINVIS)) {
if (DM_EVENT_ENABLED(vp->v_vfsp, ip, DM_EVENT_READ) && !invisible) {
int error;
vrwlock_t locktype = VRWLOCK_READ;
error = xfs_dm_send_data_event(DM_EVENT_READ, bdp, *offp,
size, FILP_DELAY_FLAG(filp), &locktype);
error = XFS_SEND_DATA(mp, DM_EVENT_READ, bdp, *offp, size,
FILP_DELAY_FLAG(filp), &locktype);
if (error) {
xfs_iunlock(ip, XFS_IOLOCK_SHARED);
return -error;
......@@ -198,7 +198,7 @@ xfs_read(
XFS_STATS_ADD(xfsstats.xs_read_bytes, ret);
if (!(filp->f_mode & FINVIS))
if (!invisible)
xfs_ichgtime(ip, XFS_ICHGTIME_ACC);
return ret;
......@@ -217,11 +217,13 @@ xfs_sendfile(
ssize_t ret;
xfs_fsize_t n;
xfs_inode_t *ip;
xfs_mount_t *mp;
vnode_t *vp;
int invisible = (filp->f_mode & FINVIS);
ip = XFS_BHVTOI(bdp);
vp = BHV_TO_VNODE(bdp);
mp = ip->i_mount;
vn_trace_entry(vp, "xfs_sendfile", (inst_t *)__return_address);
XFS_STATS_INC(xfsstats.xs_read_calls);
......@@ -241,8 +243,8 @@ xfs_sendfile(
vrwlock_t locktype = VRWLOCK_READ;
int error;
error = xfs_dm_send_data_event(DM_EVENT_READ, bdp, *offp,
count, FILP_DELAY_FLAG(filp), &locktype);
error = XFS_SEND_DATA(mp, DM_EVENT_READ, bdp, *offp, count,
FILP_DELAY_FLAG(filp), &locktype);
if (error) {
xfs_iunlock(ip, XFS_IOLOCK_SHARED);
return -error;
......@@ -493,7 +495,8 @@ xfs_write(
vnode_t *vp;
unsigned long seg;
int iolock;
int direct = file->f_flags & O_DIRECT;
int direct = (file->f_flags & O_DIRECT);
int invisible = (file->f_mode & FINVIS);
int eventsent = 0;
vrwlock_t locktype;
......@@ -573,13 +576,13 @@ xfs_write(
}
if ((DM_EVENT_ENABLED(vp->v_vfsp, xip, DM_EVENT_WRITE) &&
!(file->f_mode & FINVIS) && !eventsent)) {
!invisible && !eventsent)) {
loff_t savedsize = *offset;
xfs_iunlock(xip, XFS_ILOCK_EXCL);
error = xfs_dm_send_data_event(DM_EVENT_WRITE, bdp,
*offset, size,
FILP_DELAY_FLAG(file), &locktype);
error = XFS_SEND_DATA(xip->i_mount, DM_EVENT_WRITE, bdp,
*offset, size,
FILP_DELAY_FLAG(file), &locktype);
if (error) {
xfs_iunlock(xip, iolock);
return -error;
......@@ -588,12 +591,11 @@ xfs_write(
eventsent = 1;
/*
* The iolock was dropped and reaquired in
* xfs_dm_send_data_event 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_dm_send_data_event, which is what
* allows the size to change in the first place.
* 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) {
......@@ -608,10 +610,8 @@ xfs_write(
*
* We must update xfs' times since revalidate will overcopy xfs.
*/
if (size) {
if (!(file->f_mode & FINVIS))
xfs_ichgtime(xip, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
}
if (size && !invisible)
xfs_ichgtime(xip, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
/*
* If the offset is beyond the size of the file, we have a couple
......@@ -658,11 +658,10 @@ xfs_write(
ret = generic_file_write_nolock(file, iovp, segs, offset);
if ((ret == -ENOSPC) &&
DM_EVENT_ENABLED(vp->v_vfsp, xip, DM_EVENT_NOSPACE) &&
!(file->f_mode & FINVIS)) {
DM_EVENT_ENABLED(vp->v_vfsp, xip, DM_EVENT_NOSPACE) && !invisible) {
xfs_rwunlock(bdp, locktype);
error = dm_send_namesp_event(DM_EVENT_NOSPACE, bdp,
error = XFS_SEND_NAMESP(xip->i_mount, DM_EVENT_NOSPACE, bdp,
DM_RIGHT_NULL, bdp, DM_RIGHT_NULL, NULL, NULL,
0, 0, 0); /* Delay flag intentionally unused */
if (error)
......
/*
* Copyright (c) 2000-2001 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
......@@ -61,7 +61,6 @@ xfs_read_xfsstats(
{ "xstrat", XFSSTAT_END_WRITE_CONVERT },
{ "rw", XFSSTAT_END_READ_WRITE_OPS },
{ "attr", XFSSTAT_END_ATTRIBUTE_OPS },
{ "qm", XFSSTAT_END_QUOTA_OPS },
{ "icluster", XFSSTAT_END_INODE_CLUSTER },
{ "vnodes", XFSSTAT_END_VNODE_OPS },
};
......@@ -95,50 +94,17 @@ xfs_read_xfsstats(
return len;
}
STATIC int
xfs_read_xfsquota(
char *buffer,
char **start,
off_t offset,
int count,
int *eof,
void *data)
{
int len;
/* maximum; incore; ratio free to inuse; freelist */
len = sprintf(buffer, "%d\t%d\t%d\t%u\n",
ndquot,
xfs_Gqm? atomic_read(&xfs_Gqm->qm_totaldquots) : 0,
xfs_Gqm? xfs_Gqm->qm_dqfree_ratio : 0,
xfs_Gqm? xfs_Gqm->qm_dqfreelist.qh_nelems : 0);
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 (!proc_mkdir("fs/xfs", 0))
return;
create_proc_read_entry("fs/xfs/stat", 0, 0, xfs_read_xfsstats, NULL);
create_proc_read_entry("fs/xfs/xqm", 0, 0, xfs_read_xfsquota, NULL);
}
void
xfs_cleanup_procfs(void)
{
remove_proc_entry("fs/xfs/stat", NULL);
remove_proc_entry("fs/xfs/xqm", NULL);
remove_proc_entry("fs/xfs", NULL);
}
......@@ -107,16 +107,7 @@ struct xfsstats {
__uint32_t xs_attr_set;
__uint32_t xs_attr_remove;
__uint32_t xs_attr_list;
# define XFSSTAT_END_QUOTA_OPS (XFSSTAT_END_ATTRIBUTE_OPS+8)
__uint32_t xs_qm_dqreclaims;
__uint32_t xs_qm_dqreclaim_misses;
__uint32_t xs_qm_dquot_dups;
__uint32_t xs_qm_dqcachemisses;
__uint32_t xs_qm_dqcachehits;
__uint32_t xs_qm_dqwants;
__uint32_t xs_qm_dqshake_reclaims;
__uint32_t xs_qm_dqinact_reclaims;
# define XFSSTAT_END_INODE_CLUSTER (XFSSTAT_END_QUOTA_OPS+3)
# 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;
......
This diff is collapsed.
/*
* 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,28 +32,38 @@
#ifndef __XFS_SUPER_H__
#define __XFS_SUPER_H__
#ifdef CONFIG_XFS_POSIX_ACL
# define XFS_ACL_STRING "ACLs, "
#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 XFS_ACL_STRING
# define vfs_insertdmapi(vfs) do { } while (0)
# define vfs_initdmapi() do { } while (0)
# define vfs_exitdmapi() do { } while (0)
#endif
#ifdef CONFIG_XFS_DMAPI
# define XFS_DMAPI_STRING "DMAPI, "
#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 XFS_DMAPI_STRING
# define vfs_insertquota(vfs) do { } while (0)
# define vfs_initquota() do { } while (0)
# define vfs_exitquota() do { } while (0)
#endif
#ifdef CONFIG_XFS_QUOTA
# define XFS_QUOTA_STRING "quota, "
#ifdef CONFIG_XFS_POSIX_ACL
# define XFS_ACL_STRING "ACLs, "
# define set_posix_acl_flag(sb) ((sb)->s_flags |= MS_POSIXACL)
#else
# define XFS_QUOTA_STRING
# define XFS_ACL_STRING
# define set_posix_acl_flag(sb) do { } while (0)
#endif
#ifdef CONFIG_XFS_RT
# define XFS_RT_STRING "realtime, "
# define XFS_REALTIME_STRING "realtime, "
#else
# define XFS_RT_STRING
# define XFS_REALTIME_STRING
#endif
#ifdef CONFIG_XFS_VNODE_TRACING
......@@ -68,9 +78,9 @@
# define XFS_DBG_STRING "no debug"
#endif
#define XFS_BUILD_OPTIONS XFS_ACL_STRING XFS_DMAPI_STRING \
XFS_RT_STRING \
XFS_QUOTA_STRING XFS_VNTRACE_STRING \
#define XFS_BUILD_OPTIONS XFS_ACL_STRING \
XFS_REALTIME_STRING \
XFS_VNTRACE_STRING \
XFS_DBG_STRING /* DBG must be last */
#define LINVFS_GET_VFS(s) \
......@@ -82,6 +92,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 *,
......
/*
* 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(
struct bhv_desc *bdp,
struct xfs_mount_args *args,
struct cred *cr)
{
struct bhv_desc *next = bdp;
ASSERT(next);
while (! (bhvtovfsops(next))->vfs_mount)
next = BHV_NEXT(next);
return ((*bhvtovfsops(next)->vfs_mount)(next, args, cr));
}
int
vfs_parseargs(
struct bhv_desc *bdp,
char *s,
struct xfs_mount_args *args,
int f)
{
struct bhv_desc *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(
struct bhv_desc *bdp,
struct seq_file *m)
{
struct bhv_desc *next = bdp;
ASSERT(next);
while (! (bhvtovfsops(next))->vfs_showargs)
next = BHV_NEXT(next);
return ((*bhvtovfsops(next)->vfs_showargs)(next, m));
}
int
vfs_unmount(
struct bhv_desc *bdp,
int fl,
struct cred *cr)
{
struct bhv_desc *next = bdp;
ASSERT(next);
while (! (bhvtovfsops(next))->vfs_unmount)
next = BHV_NEXT(next);
return ((*bhvtovfsops(next)->vfs_unmount)(next, fl, cr));
}
int
vfs_root(
struct bhv_desc *bdp,
struct vnode **vpp)
{
struct bhv_desc *next = bdp;
ASSERT(next);
while (! (bhvtovfsops(next))->vfs_root)
next = BHV_NEXT(next);
return ((*bhvtovfsops(next)->vfs_root)(next, vpp));
}
int
vfs_statvfs(
struct bhv_desc *bdp,
struct statfs *sp,
struct vnode *vp)
{
struct bhv_desc *next = bdp;
ASSERT(next);
while (! (bhvtovfsops(next))->vfs_statvfs)
next = BHV_NEXT(next);
return ((*bhvtovfsops(next)->vfs_statvfs)(next, sp, vp));
}
int
vfs_sync(
struct bhv_desc *bdp,
int fl,
struct cred *cr)
{
struct bhv_desc *next = bdp;
ASSERT(next);
while (! (bhvtovfsops(next))->vfs_sync)
next = BHV_NEXT(next);
return ((*bhvtovfsops(next)->vfs_sync)(next, fl, cr));
}
int
vfs_vget(
struct bhv_desc *bdp,
struct vnode **vpp,
struct fid *fidp)
{
struct bhv_desc *next = bdp;
ASSERT(next);
while (! (bhvtovfsops(next))->vfs_vget)
next = BHV_NEXT(next);
return ((*bhvtovfsops(next)->vfs_vget)(next, vpp, fidp));
}
int
vfs_dmapiops(
struct bhv_desc *bdp,
caddr_t addr)
{
struct bhv_desc *next = bdp;
ASSERT(next);
while (! (bhvtovfsops(next))->vfs_dmapiops)
next = BHV_NEXT(next);
return ((*bhvtovfsops(next)->vfs_dmapiops)(next, addr));
}
int
vfs_quotactl(
struct bhv_desc *bdp,
int cmd,
int id,
caddr_t addr)
{
struct bhv_desc *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(
struct bhv_desc *bdp,
struct vnode *vp,
struct bhv_desc *bp,
int unlock)
{
struct bhv_desc *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(
struct bhv_desc *bdp,
int fl,
char *file,
int line)
{
struct bhv_desc *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 )
{
struct vfs *vfsp;
vfsp = kmem_zalloc(sizeof(vfs_t), KM_SLEEP);
bhv_head_init(VFS_BHVHEAD(vfsp), "vfs");
return vfsp;
}
void
vfs_deallocate(
struct vfs *vfsp)
{
bhv_head_destroy(VFS_BHVHEAD(vfsp));
kmem_free(vfsp, sizeof(vfs_t));
}
void
vfs_insertops(
struct 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 vfs *vfsp,
struct bhv_desc *bdp,
struct vfsops *vfsops,
void *mount)
{
bhv_desc_init(bdp, mount, vfsp, vfsops);
bhv_insert_initial(&vfsp->vfs_bh, bdp);
}
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);
}
This diff is collapsed.
/*
* 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,7 +31,6 @@
*/
#include <xfs.h>
#include <linux/pagemap.h>
uint64_t vn_generation; /* vnode generation number */
......@@ -73,19 +72,19 @@ vn_init(void)
* Clean a vnode of filesystem-specific data and prepare it for reuse.
*/
STATIC int
vn_reclaim(struct vnode *vp)
vn_reclaim(
struct vnode *vp)
{
int error;
int error;
XFS_STATS_INC(xfsstats.vn_reclaim);
vn_trace_entry(vp, "vn_reclaim", (inst_t *)__return_address);
/*
* Only make the VOP_RECLAIM call if there are behaviors
* to call.
*/
if (vp->v_fbhv != NULL) {
if (vp->v_fbhv) {
VOP_RECLAIM(vp, error);
if (error)
return -error;
......@@ -108,18 +107,19 @@ vn_reclaim(struct vnode *vp)
}
STATIC void
vn_wakeup(struct vnode *vp)
vn_wakeup(
struct vnode *vp)
{
VN_LOCK(vp);
if (vp->v_flag & VWAIT) {
if (vp->v_flag & VWAIT)
sv_broadcast(vptosync(vp));
}
vp->v_flag &= ~(VRECLM|VWAIT|VMODIFIED);
VN_UNLOCK(vp, 0);
}
int
vn_wait(struct vnode *vp)
vn_wait(
struct vnode *vp)
{
VN_LOCK(vp);
if (vp->v_flag & (VINACT | VRECLM)) {
......@@ -132,7 +132,8 @@ vn_wait(struct vnode *vp)
}
struct vnode *
vn_initialize(struct inode *inode)
vn_initialize(
struct inode *inode)
{
struct vnode *vp = LINVFS_GET_VP(inode);
......@@ -165,7 +166,9 @@ vn_initialize(struct inode *inode)
* Get a reference on a vnode.
*/
vnode_t *
vn_get(struct vnode *vp, vmap_t *vmap)
vn_get(
struct vnode *vp,
vmap_t *vmap)
{
struct inode *inode;
......@@ -175,7 +178,7 @@ vn_get(struct vnode *vp, vmap_t *vmap)
return NULL;
inode = ilookup(vmap->v_vfsp->vfs_super, vmap->v_ino);
if (inode == NULL) /* Inode not present */
if (!inode) /* Inode not present */
return NULL;
vn_trace_exit(vp, "vn_get", (inst_t *)__return_address);
......@@ -187,16 +190,17 @@ vn_get(struct vnode *vp, vmap_t *vmap)
* Revalidate the Linux inode from the vnode.
*/
int
vn_revalidate(struct vnode *vp)
vn_revalidate(
struct vnode *vp)
{
int error;
struct inode *inode;
vattr_t va;
int error;
vn_trace_entry(vp, "vn_revalidate", (inst_t *)__return_address);
ASSERT(vp->v_fbhv != NULL);
va.va_mask = XFS_AT_STAT|XFS_AT_GENCOUNT;
va.va_mask = XFS_AT_STAT;
VOP_GETATTR(vp, &va, 0, NULL, error);
if (!error) {
inode = LINVFS_GET_IP(vp);
......@@ -206,12 +210,9 @@ vn_revalidate(struct vnode *vp)
inode->i_gid = va.va_gid;
inode->i_size = va.va_size;
inode->i_blocks = va.va_nblocks;
inode->i_mtime.tv_sec = va.va_mtime.tv_sec;
inode->i_mtime.tv_nsec = va.va_mtime.tv_nsec;
inode->i_ctime.tv_sec = va.va_ctime.tv_sec;
inode->i_ctime.tv_nsec = va.va_ctime.tv_nsec;
inode->i_atime.tv_sec = va.va_atime.tv_sec;
inode->i_atime.tv_nsec = va.va_atime.tv_nsec;
inode->i_mtime = va.va_mtime;
inode->i_ctime = va.va_ctime;
inode->i_atime = va.va_atime;
VUNMODIFY(vp);
}
return -error;
......@@ -224,7 +225,9 @@ vn_revalidate(struct vnode *vp)
* get a handle (via vn_get) on the vnode (usually done via a mount/vfs lock).
*/
void
vn_purge(struct vnode *vp, vmap_t *vmap)
vn_purge(
struct vnode *vp,
vmap_t *vmap)
{
vn_trace_entry(vp, "vn_purge", (inst_t *)__return_address);
......@@ -284,9 +287,10 @@ vn_purge(struct vnode *vp, vmap_t *vmap)
* Add a reference to a referenced vnode.
*/
struct vnode *
vn_hold(struct vnode *vp)
vn_hold(
struct vnode *vp)
{
struct inode *inode;
struct inode *inode;
XFS_STATS_INC(xfsstats.vn_hold);
......@@ -302,10 +306,11 @@ vn_hold(struct vnode *vp)
* Call VOP_INACTIVE on last reference.
*/
void
vn_rele(struct vnode *vp)
vn_rele(
struct vnode *vp)
{
int vcnt;
int cache;
int vcnt;
int cache;
XFS_STATS_INC(xfsstats.vn_rele);
......@@ -319,7 +324,7 @@ vn_rele(struct vnode *vp)
* that i_count won't be decremented after we
* return.
*/
if (vcnt == 0) {
if (!vcnt) {
/*
* As soon as we turn this on, noone can find us in vn_get
* until we turn off VINACT or VRECLM
......@@ -331,19 +336,14 @@ vn_rele(struct vnode *vp)
* Do not make the VOP_INACTIVE call if there
* are no behaviors attached to the vnode to call.
*/
if (vp->v_fbhv != NULL) {
if (vp->v_fbhv)
VOP_INACTIVE(vp, NULL, cache);
}
VN_LOCK(vp);
if (vp->v_flag & VWAIT) {
if (vp->v_flag & VWAIT) {
sv_broadcast(vptosync(vp));
}
}
if (vp->v_flag & VWAIT)
sv_broadcast(vptosync(vp));
vp->v_flag &= ~(VINACT|VWAIT|VRECLM|VMODIFIED);
}
VN_UNLOCK(vp, 0);
......@@ -355,17 +355,16 @@ vn_rele(struct vnode *vp)
* Finish the removal of a vnode.
*/
void
vn_remove(struct vnode *vp)
vn_remove(
struct vnode *vp)
{
/* REFERENCED */
vmap_t vmap;
vmap_t vmap;
/* Make sure we don't do this to the same vnode twice */
if (!(vp->v_fbhv))
return;
XFS_STATS_INC(xfsstats.vn_remove);
vn_trace_exit(vp, "vn_remove", (inst_t *)__return_address);
/*
......
/*
* 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,
......@@ -267,163 +262,92 @@ 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); \
}
#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);\
}
#define VOP_READ(vp,file,iov,segs,offset,cr,rv) \
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,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
......
......@@ -1290,7 +1290,7 @@ bio_end_io_pagebuf(
if (atomic_dec_and_test(&pb->pb_io_remaining) == 1) {
pb->pb_locked = 0;
pagebuf_iodone(pb, 0, 1);
pagebuf_iodone(pb, (pb->pb_flags & PBF_FS_DATAIOD), 1);
}
bio_put(bio);
......@@ -1434,7 +1434,7 @@ pagebuf_iorequest( /* start real I/O */
if (atomic_dec_and_test(&pb->pb_io_remaining) == 1) {
pb->pb_locked = 0;
pagebuf_iodone(pb, 0, 0);
pagebuf_iodone(pb, (pb->pb_flags & PBF_FS_DATAIOD), 1);
}
return 0;
......@@ -1612,15 +1612,13 @@ pagebuf_daemon(
refrigerator(PF_IOTHREAD);
if (pbd_active == 1) {
del_timer(&pb_daemon_timer);
pb_daemon_timer.expires = jiffies +
pb_params.p_un.flush_interval;
add_timer(&pb_daemon_timer);
mod_timer(&pb_daemon_timer,
jiffies + pb_params.p_un.flush_interval);
interruptible_sleep_on(&pbd_waitq);
}
if (pbd_active == 0) {
del_timer(&pb_daemon_timer);
del_timer_sync(&pb_daemon_timer);
}
spin_lock(&pbd_delwrite_lock);
......
......@@ -96,6 +96,7 @@ typedef enum page_buf_flags_e { /* pb_flags values */
PBF_MAPPABLE = (1 << 9),/* use directly-addressable pages */
PBF_STALE = (1 << 10), /* buffer has been staled, do not find it */
PBF_FS_MANAGED = (1 << 11), /* filesystem controls freeing memory */
PBF_FS_DATAIOD = (1 << 12), /* schedule IO completion on fs datad */
/* flags used only as arguments to access routines */
PBF_LOCK = (1 << 13), /* lock requested */
......
......@@ -146,6 +146,7 @@ XFS_DQ_IS_LOCKED(xfs_dquot_t *dqp)
}
#endif
/*
* The following three routines simply manage the q_flock
* semaphore embedded in the dquot. This semaphore synchronizes
......@@ -197,7 +198,6 @@ extern void xfs_qm_dqprint(xfs_dquot_t *);
#define xfs_qm_dqprint(a)
#endif
extern xfs_dquot_t *xfs_qm_dqinit(xfs_mount_t *, xfs_dqid_t, uint);
extern void xfs_qm_dqdestroy(xfs_dquot_t *);
extern int xfs_qm_dqflush(xfs_dquot_t *, uint);
extern int xfs_qm_dqpurge(xfs_dquot_t *, uint);
......@@ -206,7 +206,15 @@ extern int xfs_qm_dqlock_nowait(xfs_dquot_t *);
extern int xfs_qm_dqflock_nowait(xfs_dquot_t *);
extern void xfs_qm_dqflock_pushbuf_wait(xfs_dquot_t *dqp);
extern void xfs_qm_adjust_dqtimers(xfs_mount_t *,
xfs_disk_dquot_t *);
xfs_disk_dquot_t *);
extern int xfs_qm_dqwarn(xfs_disk_dquot_t *, uint);
extern int xfs_qm_dqget(xfs_mount_t *, xfs_inode_t *,
xfs_dqid_t, uint, uint, xfs_dquot_t **);
extern void xfs_qm_dqput(xfs_dquot_t *);
extern void xfs_qm_dqrele(xfs_dquot_t *);
extern void xfs_dqlock(xfs_dquot_t *);
extern void xfs_dqlock2(xfs_dquot_t *, xfs_dquot_t *);
extern void xfs_dqunlock(xfs_dquot_t *);
extern void xfs_dqunlock_nonotify(xfs_dquot_t *);
#endif /* __XFS_DQUOT_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
......@@ -31,7 +31,7 @@
*/
#include <xfs.h>
#include <xfs_quota_priv.h>
#include "xfs_qm.h"
/*
......
/*
* Copyright (c) 2000-2001 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,58 +32,22 @@
#ifndef __XFS_DQUOT_ITEM_H__
#define __XFS_DQUOT_ITEM_H__
/*
* These are the structures used to lay out dquots and quotaoff
* records on the log. Quite similar to those of inodes.
*/
/*
* log format struct for dquots.
* The first two fields must be the type and size fitting into
* 32 bits : log_recovery code assumes that.
*/
typedef struct xfs_dq_logformat {
__uint16_t qlf_type; /* dquot log item type */
__uint16_t qlf_size; /* size of this item */
xfs_dqid_t qlf_id; /* usr/grp id number : 32 bits */
__int64_t qlf_blkno; /* blkno of dquot buffer */
__int32_t qlf_len; /* len of dquot buffer */
__uint32_t qlf_boffset; /* off of dquot in buffer */
} xfs_dq_logformat_t;
/*
* log format struct for QUOTAOFF records.
* The first two fields must be the type and size fitting into
* 32 bits : log_recovery code assumes that.
* We write two LI_QUOTAOFF logitems per quotaoff, the last one keeps a pointer
* to the first and ensures that the first logitem is taken out of the AIL
* only when the last one is securely committed.
*/
typedef struct xfs_qoff_logformat {
unsigned short qf_type; /* quotaoff log item type */
unsigned short qf_size; /* size of this item */
unsigned int qf_flags; /* USR and/or GRP */
char qf_pad[12]; /* padding for future */
} xfs_qoff_logformat_t;
#ifdef __KERNEL__
struct xfs_dquot;
struct xfs_trans;
struct xfs_mount;
struct xfs_qoff_logitem;
typedef struct xfs_dq_logitem {
xfs_log_item_t qli_item; /* common portion */
struct xfs_dquot *qli_dquot; /* dquot ptr */
xfs_lsn_t qli_flush_lsn; /* lsn at last flush */
unsigned short qli_pushbuf_flag; /* one bit used in push_ail */
unsigned short qli_pushbuf_flag; /* 1 bit used in push_ail */
#ifdef DEBUG
uint64_t qli_push_owner;
#endif
xfs_dq_logformat_t qli_format; /* logged structure */
} xfs_dq_logitem_t;
typedef struct xfs_qoff_logitem {
xfs_log_item_t qql_item; /* common portion */
struct xfs_qoff_logitem *qql_start_lip; /* qoff-start logitem, if any */
......@@ -93,12 +57,10 @@ typedef struct xfs_qoff_logitem {
extern void xfs_qm_dquot_logitem_init(struct xfs_dquot *);
extern xfs_qoff_logitem_t *xfs_qm_qoff_logitem_init(struct xfs_mount *,
xfs_qoff_logitem_t *, uint);
struct xfs_qoff_logitem *, uint);
extern xfs_qoff_logitem_t *xfs_trans_get_qoff_item(struct xfs_trans *,
xfs_qoff_logitem_t *, uint);
struct xfs_qoff_logitem *, uint);
extern void xfs_trans_log_quotaoff_item(struct xfs_trans *,
xfs_qoff_logitem_t *);
#endif /* __KERNEL__ */
struct xfs_qoff_logitem *);
#endif /* __XFS_DQUOT_ITEM_H__ */
This diff is collapsed.
/*
* 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,16 @@
#ifndef __XFS_QM_H__
#define __XFS_QM_H__
struct xfs_dqhash;
struct xfs_inode;
struct xfs_dquot;
#include "xfs_dquot_item.h"
#include "xfs_dquot.h"
#include "xfs_quota_priv.h"
#include "xfs_qm_stats.h"
struct xfs_qm;
struct xfs_inode;
extern mutex_t xfs_Gqm_lock;
extern struct xfs_qm *xfs_Gqm;
extern kmem_zone_t *qm_dqzone;
extern kmem_zone_t *qm_dqtrxzone;
......@@ -136,24 +142,13 @@ typedef struct xfs_quotainfo {
} xfs_quotainfo_t;
/*
* The structure kept inside the xfs_trans_t keep track of dquot changes
* within a transaction and apply them later.
*/
typedef struct xfs_dqtrx {
struct xfs_dquot *qt_dquot; /* the dquot this refers to */
ulong qt_blk_res; /* blks reserved on a dquot */
ulong qt_blk_res_used; /* blks used from the reservation */
ulong qt_ino_res; /* inode reserved on a dquot */
ulong qt_ino_res_used; /* inodes used from the reservation */
long qt_bcount_delta; /* dquot blk count changes */
long qt_delbcnt_delta; /* delayed dquot blk count changes */
long qt_icount_delta; /* dquot inode count changes */
ulong qt_rtblk_res; /* # blks reserved on a dquot */
ulong qt_rtblk_res_used;/* # blks used from reservation */
long qt_rtbcount_delta;/* dquot realtime blk changes */
long qt_delrtb_delta; /* delayed RT blk count changes */
} xfs_dqtrx_t;
extern xfs_dqtrxops_t xfs_trans_dquot_ops;
extern void xfs_trans_mod_dquot(xfs_trans_t *, xfs_dquot_t *, uint, long);
extern int xfs_trans_reserve_quota_bydquots(xfs_trans_t *, xfs_mount_t *,
xfs_dquot_t *, xfs_dquot_t *, long, long, uint);
extern void xfs_trans_dqjoin(xfs_trans_t *, xfs_dquot_t *);
extern void xfs_trans_log_dquot(xfs_trans_t *, xfs_dquot_t *);
/*
* We keep the usr and grp dquots separately so that locking will be easier
......@@ -184,9 +179,33 @@ typedef struct xfs_dquot_acct {
extern int xfs_qm_init_quotainfo(xfs_mount_t *);
extern void xfs_qm_destroy_quotainfo(xfs_mount_t *);
extern int xfs_qm_mount_quotas(xfs_mount_t *);
extern void xfs_qm_mount_quotainit(xfs_mount_t *, uint);
extern void xfs_qm_unmount_quotadestroy(xfs_mount_t *);
extern int xfs_qm_unmount_quotas(xfs_mount_t *);
extern int xfs_qm_write_sb_changes(xfs_mount_t *, __int64_t);
extern int xfs_qm_sync(xfs_mount_t *, short);
/* dquot stuff */
extern void xfs_qm_dqunlink(xfs_dquot_t *);
extern boolean_t xfs_qm_dqalloc_incore(xfs_dquot_t **);
extern int xfs_qm_write_sb_changes(xfs_mount_t *, __int64_t);
extern int xfs_qm_dqattach(xfs_inode_t *, uint);
extern void xfs_qm_dqdetach(xfs_inode_t *);
extern int xfs_qm_dqpurge_all(xfs_mount_t *, uint);
extern void xfs_qm_dqrele_all_inodes(xfs_mount_t *, uint);
/* vop stuff */
extern int xfs_qm_vop_dqalloc(xfs_mount_t *, xfs_inode_t *,
uid_t, gid_t, uint,
xfs_dquot_t **, xfs_dquot_t **);
extern void xfs_qm_vop_dqattach_and_dqmod_newinode(
xfs_trans_t *, xfs_inode_t *,
xfs_dquot_t *, xfs_dquot_t *);
extern int xfs_qm_vop_rename_dqattach(xfs_inode_t **);
extern xfs_dquot_t * xfs_qm_vop_chown(xfs_trans_t *, xfs_inode_t *,
xfs_dquot_t **, xfs_dquot_t *);
extern int xfs_qm_vop_chown_reserve(xfs_trans_t *, xfs_inode_t *,
xfs_dquot_t *, xfs_dquot_t *, uint);
/* list stuff */
extern void xfs_qm_freelist_init(xfs_frlist_t *);
......@@ -199,10 +218,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 *);
......@@ -210,10 +226,4 @@ extern int xfs_qm_internalqcheck(xfs_mount_t *);
#define xfs_qm_internalqcheck(mp) (0)
#endif
#ifdef QUOTADEBUG
extern void xfs_qm_freelist_print(xfs_frlist_t *, char *);
#else
#define xfs_qm_freelist_print(a, b) do { } while (0)
#endif
#endif /* __XFS_QM_H__ */
This diff is collapsed.
/*
* Copyright (c) 2000-2001 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
......@@ -29,71 +29,89 @@
*
* http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
*/
#ifndef __XFS_DQBLK_H__
#define __XFS_DQBLK_H__
/*
* The ondisk form of a dquot structure.
*/
#define XFS_DQUOT_MAGIC 0x4451 /* 'DQ' */
#define XFS_DQUOT_VERSION (u_int8_t)0x01 /* latest version number */
#include <xfs.h>
#include <linux/proc_fs.h>
#include "xfs_qm.h"
/*
* This is the main portion of the on-disk representation of quota
* information for a user. This is the q_core of the xfs_dquot_t that
* is kept in kernel memory. We pad this with some more expansion room
* to construct the on disk structure.
*/
typedef struct xfs_disk_dquot {
/*16*/ u_int16_t d_magic; /* dquot magic = XFS_DQUOT_MAGIC */
/*8 */ u_int8_t d_version; /* dquot version */
/*8 */ u_int8_t d_flags; /* XFS_DQ_USER/PROJ/GROUP */
/*32*/ xfs_dqid_t d_id; /* user,project,group id */
/*64*/ xfs_qcnt_t d_blk_hardlimit;/* absolute limit on disk blks */
/*64*/ xfs_qcnt_t d_blk_softlimit;/* preferred limit on disk blks */
/*64*/ xfs_qcnt_t d_ino_hardlimit;/* maximum # allocated inodes */
/*64*/ xfs_qcnt_t d_ino_softlimit;/* preferred inode limit */
/*64*/ xfs_qcnt_t d_bcount; /* disk blocks owned by the user */
/*64*/ xfs_qcnt_t d_icount; /* inodes owned by the user */
/*32*/ __int32_t d_itimer; /* zero if within inode limits if not,
this is when we refuse service */
/*32*/ __int32_t d_btimer; /* similar to above; for disk blocks */
/*16*/ xfs_qwarncnt_t d_iwarns; /* warnings issued wrt num inodes */
/*16*/ xfs_qwarncnt_t d_bwarns; /* warnings issued wrt disk blocks */
/*32*/ __int32_t d_pad0; /* 64 bit align */
/*64*/ xfs_qcnt_t d_rtb_hardlimit;/* absolute limit on realtime blks */
/*64*/ xfs_qcnt_t d_rtb_softlimit;/* preferred limit on RT disk blks */
/*64*/ xfs_qcnt_t d_rtbcount; /* realtime blocks owned */
/*32*/ __int32_t d_rtbtimer; /* similar to above; for RT disk blocks */
/*16*/ xfs_qwarncnt_t d_rtbwarns; /* warnings issued wrt RT disk blocks */
/*16*/ __uint16_t d_pad;
} xfs_disk_dquot_t;
struct xqmstats xqmstats;
/*
* This is what goes on disk. This is separated from the xfs_disk_dquot because
* carrying the unnecessary padding would be a waste of memory.
*/
typedef struct xfs_dqblk {
xfs_disk_dquot_t dd_diskdq; /* portion that lives incore as well */
char dd_fill[32]; /* filling for posterity */
} xfs_dqblk_t;
STATIC int
xfs_qm_read_xfsquota(
char *buffer,
char **start,
off_t offset,
int count,
int *eof,
void *data)
{
int len;
/*
* flags for q_flags field in the dquot.
*/
#define XFS_DQ_USER 0x0001 /* a user quota */
/* #define XFS_DQ_PROJ 0x0002 -- project quota (IRIX) */
#define XFS_DQ_GROUP 0x0004 /* a group quota */
#define XFS_DQ_FLOCKED 0x0008 /* flush lock taken */
#define XFS_DQ_DIRTY 0x0010 /* dquot is dirty */
#define XFS_DQ_WANT 0x0020 /* for lookup/reclaim race */
#define XFS_DQ_INACTIVE 0x0040 /* dq off mplist & hashlist */
#define XFS_DQ_MARKER 0x0080 /* sentinel */
/* maximum; incore; ratio free to inuse; freelist */
len = sprintf(buffer, "%d\t%d\t%d\t%u\n",
ndquot,
xfs_Gqm? atomic_read(&xfs_Gqm->qm_totaldquots) : 0,
xfs_Gqm? xfs_Gqm->qm_dqfree_ratio : 0,
xfs_Gqm? xfs_Gqm->qm_dqfreelist.qh_nelems : 0);
/*
* In the worst case, when both user and group quotas are on,
* we can have a max of three dquots changing in a single transaction.
*/
#define XFS_DQUOT_LOGRES(mp) (sizeof(xfs_disk_dquot_t) * 3)
if (offset >= len) {
*start = buffer;
*eof = 1;
return 0;
}
*start = buffer + offset;
if ((len -= offset) > count)
return count;
*eof = 1;
return len;
}
STATIC int
xfs_qm_read_stats(
char *buffer,
char **start,
off_t offset,
int count,
int *eof,
void *data)
{
int len;
/* quota performance statistics */
len = sprintf(buffer, "qm %u %u %u %u %u %u %u %u\n",
xqmstats.xs_qm_dqreclaims,
xqmstats.xs_qm_dqreclaim_misses,
xqmstats.xs_qm_dquot_dups,
xqmstats.xs_qm_dqcachemisses,
xqmstats.xs_qm_dqcachehits,
xqmstats.xs_qm_dqwants,
xqmstats.xs_qm_dqshake_reclaims,
xqmstats.xs_qm_dqinact_reclaims);
if (offset >= len) {
*start = buffer;
*eof = 1;
return 0;
}
*start = buffer + offset;
if ((len -= offset) > count)
return count;
*eof = 1;
return len;
}
void
xfs_qm_init_procfs(void)
{
create_proc_read_entry("fs/xfs/xqmstat", 0, 0, xfs_qm_read_stats, NULL);
create_proc_read_entry("fs/xfs/xqm", 0, 0, xfs_qm_read_xfsquota, NULL);
}
#endif /* __XFS_DQBLK_H__ */
void
xfs_qm_cleanup_procfs(void)
{
remove_proc_entry("fs/xfs/xqm", NULL);
remove_proc_entry("fs/xfs/xqmstat", NULL);
}
/*
* Copyright (c) 2002 Silicon Graphics, Inc. All Rights Reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it would be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*
* Further, this software is distributed without any warranty that it is
* free of the rightful claim of any third person regarding infringement
* or the like. Any license provided herein, whether implied or
* otherwise, applies only to this software file. Patent licenses, if
* any, provided herein do not apply to combinations of this program with
* other software, or any other product whatsoever.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write the Free Software Foundation, Inc., 59
* Temple Place - Suite 330, Boston MA 02111-1307, USA.
*
* Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
* Mountain View, CA 94043, or:
*
* http://www.sgi.com
*
* For further information regarding this notice, see:
*
* http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
*/
#ifndef __XFS_QM_STATS_H__
#define __XFS_QM_STATS_H__
#if defined(CONFIG_PROC_FS) && !defined(XFS_STATS_OFF)
/*
* XQM global statistics
*/
struct xqmstats {
__uint32_t xs_qm_dqreclaims;
__uint32_t xs_qm_dqreclaim_misses;
__uint32_t xs_qm_dquot_dups;
__uint32_t xs_qm_dqcachemisses;
__uint32_t xs_qm_dqcachehits;
__uint32_t xs_qm_dqwants;
__uint32_t xs_qm_dqshake_reclaims;
__uint32_t xs_qm_dqinact_reclaims;
};
extern struct xqmstats xqmstats;
# define XQM_STATS_INC(count) ( (count)++ )
extern void xfs_qm_init_procfs(void);
extern void xfs_qm_cleanup_procfs(void);
#else
# define XQM_STATS_INC(count) do { } while (0)
static __inline void xfs_qm_init_procfs(void) { };
static __inline void xfs_qm_cleanup_procfs(void) { };
#endif
#endif /* __XFS_QM_STATS_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
......@@ -67,8 +67,8 @@
#define XQMLCK(h) (mutex_lock(&((h)->qh_lock), PINOD))
#define XQMUNLCK(h) (mutex_unlock(&((h)->qh_lock)))
#ifdef DEBUG
static inline int
XQMISLCKD(xfs_dqhash_t *h)
struct xfs_dqhash;
static inline int XQMISLCKD(struct xfs_dqhash *h)
{
if (mutex_trylock(&h->qh_lock)) {
mutex_unlock(&h->qh_lock);
......
......@@ -31,8 +31,9 @@
*/
#include <xfs.h>
#include <xfs_quota_priv.h>
#include "xfs_qm.h"
STATIC void xfs_trans_alloc_dqinfo(xfs_trans_t *);
/*
* Add the locked dquot to the transaction.
......@@ -95,7 +96,7 @@ xfs_trans_log_dquot(
* Carry forward whatever is left of the quota blk reservation to
* the spanky new transaction
*/
void
STATIC void
xfs_trans_dup_dqinfo(
xfs_trans_t *otp,
xfs_trans_t *ntp)
......@@ -104,6 +105,9 @@ xfs_trans_dup_dqinfo(
int i,j;
xfs_dqtrx_t *oqa, *nqa;
if (!otp->t_dqinfo)
return;
xfs_trans_alloc_dqinfo(ntp);
oqa = otp->t_dqinfo->dqa_usrdquots;
nqa = ntp->t_dqinfo->dqa_usrdquots;
......@@ -155,15 +159,23 @@ xfs_trans_mod_dquot_byino(
uint field,
long delta)
{
xfs_mount_t *mp;
ASSERT(tp);
mp = tp->t_mountp;
if (!XFS_IS_QUOTA_ON(mp) ||
ip->i_ino == mp->m_sb.sb_uquotino ||
ip->i_ino == mp->m_sb.sb_gquotino)
return;
if (tp->t_dqinfo == NULL)
xfs_trans_alloc_dqinfo(tp);
if (XFS_IS_UQUOTA_ON(tp->t_mountp) && ip->i_udquot) {
if (XFS_IS_UQUOTA_ON(mp) && ip->i_udquot) {
(void) xfs_trans_mod_dquot(tp, ip->i_udquot, field, delta);
}
if (XFS_IS_GQUOTA_ON(tp->t_mountp) && ip->i_gdquot) {
if (XFS_IS_GQUOTA_ON(mp) && ip->i_gdquot) {
(void) xfs_trans_mod_dquot(tp, ip->i_gdquot, field, delta);
}
}
......@@ -318,7 +330,7 @@ xfs_trans_dqlockedjoin(
* xfs_trans_apply_sb_deltas().
* Go thru all the dquots belonging to this transaction and modify the
* INCORE dquot to reflect the actual usages.
* Unreserve just the reservations done by this transaction
* Unreserve just the reservations done by this transaction.
* dquot is still left locked at exit.
*/
void
......@@ -332,6 +344,9 @@ xfs_trans_apply_dquot_deltas(
long totalbdelta;
long totalrtbdelta;
if (! (tp->t_flags & XFS_TRANS_DQ_DIRTY))
return;
ASSERT(tp->t_dqinfo);
qa = tp->t_dqinfo->dqa_usrdquots;
for (j = 0; j < 2; j++) {
......@@ -481,13 +496,15 @@ xfs_trans_apply_dquot_deltas(
#ifdef QUOTADEBUG
if (qtrx->qt_rtblk_res != 0)
printk("RT res %d for 0x%p\n",
(int) qtrx->qt_rtblk_res,
dqp);
cmn_err(CE_DEBUG, "RT res %d for 0x%p\n",
(int) qtrx->qt_rtblk_res, dqp);
#endif
ASSERT(dqp->q_res_bcount >= INT_GET(dqp->q_core.d_bcount, ARCH_CONVERT));
ASSERT(dqp->q_res_icount >= INT_GET(dqp->q_core.d_icount, ARCH_CONVERT));
ASSERT(dqp->q_res_rtbcount >= INT_GET(dqp->q_core.d_rtbcount, ARCH_CONVERT));
ASSERT(dqp->q_res_bcount >=
INT_GET(dqp->q_core.d_bcount, ARCH_CONVERT));
ASSERT(dqp->q_res_icount >=
INT_GET(dqp->q_core.d_icount, ARCH_CONVERT));
ASSERT(dqp->q_res_rtbcount >=
INT_GET(dqp->q_core.d_rtbcount, ARCH_CONVERT));
}
/*
* Do the group quotas next
......@@ -503,16 +520,18 @@ xfs_trans_apply_dquot_deltas(
* we simply throw those away, since that's the expected behavior
* when a transaction is curtailed without a commit.
*/
void
STATIC void
xfs_trans_unreserve_and_mod_dquots(
xfs_trans_t *tp)
xfs_trans_t *tp)
{
int i, j;
xfs_dquot_t *dqp;
xfs_dqtrx_t *qtrx, *qa;
boolean_t locked;
ASSERT(tp->t_dqinfo);
if (!tp->t_dqinfo || !(tp->t_flags & XFS_TRANS_DQ_DIRTY))
return;
qa = tp->t_dqinfo->dqa_usrdquots;
for (j = 0; j < 2; j++) {
......@@ -604,8 +623,8 @@ xfs_trans_dqresv(
!INT_ISZERO(dqp->q_core.d_id, ARCH_CONVERT) &&
XFS_IS_QUOTA_ENFORCED(dqp->q_mount)) {
#ifdef QUOTADEBUG
printk("BLK Res: nblks=%ld + resbcount=%Ld > hardlimit=%Ld?\n",
nblks, *resbcountp, hardlimit);
cmn_err(CE_DEBUG, "BLK Res: nblks=%ld + resbcount=%Ld"
" > hardlimit=%Ld?", nblks, *resbcountp, hardlimit);
#endif
if (nblks > 0) {
/*
......@@ -713,6 +732,7 @@ xfs_trans_dqresv(
int
xfs_trans_reserve_quota_bydquots(
xfs_trans_t *tp,
xfs_mount_t *mp,
xfs_dquot_t *udqp,
xfs_dquot_t *gdqp,
long nblks,
......@@ -721,6 +741,9 @@ xfs_trans_reserve_quota_bydquots(
{
int resvd;
if (! XFS_IS_QUOTA_ON(mp))
return (0);
if (tp && tp->t_dqinfo == NULL)
xfs_trans_alloc_dqinfo(tp);
......@@ -760,15 +783,22 @@ xfs_trans_reserve_quota_bydquots(
*
* Returns 0 on success, EDQUOT or other errors otherwise
*/
int
STATIC int
xfs_trans_reserve_quota_nblks(
xfs_trans_t *tp,
xfs_mount_t *mp,
xfs_inode_t *ip,
long nblks,
long ninos,
uint type)
{
int error;
int error;
if (!XFS_IS_QUOTA_ON(mp))
return (0);
ASSERT(ip->i_ino != mp->m_sb.sb_uquotino);
ASSERT(ip->i_ino != mp->m_sb.sb_gquotino);
#ifdef QUOTADEBUG
if (ip->i_udquot)
......@@ -785,7 +815,7 @@ xfs_trans_reserve_quota_nblks(
/*
* Reserve nblks against these dquots, with trans as the mediator.
*/
error = xfs_trans_reserve_quota_bydquots(tp,
error = xfs_trans_reserve_quota_bydquots(tp, mp,
ip->i_udquot, ip->i_gdquot,
nblks, ninos,
type);
......@@ -836,17 +866,29 @@ xfs_trans_log_quotaoff_item(
lidp->lid_flags |= XFS_LID_DIRTY;
}
void
STATIC void
xfs_trans_alloc_dqinfo(
xfs_trans_t *tp)
{
(tp)->t_dqinfo = kmem_zone_zalloc(xfs_Gqm->qm_dqtrxzone, KM_SLEEP);
}
void
STATIC void
xfs_trans_free_dqinfo(
xfs_trans_t *tp)
{
if (!tp->t_dqinfo)
return;
kmem_zone_free(xfs_Gqm->qm_dqtrxzone, (tp)->t_dqinfo);
(tp)->t_dqinfo = NULL;
}
xfs_dqtrxops_t xfs_trans_dquot_ops = {
.qo_dup_dqinfo = xfs_trans_dup_dqinfo,
.qo_free_dqinfo = xfs_trans_free_dqinfo,
.qo_mod_dquot_byino = xfs_trans_mod_dquot_byino,
.qo_apply_dquot_deltas = xfs_trans_apply_dquot_deltas,
.qo_reserve_quota_nblks = xfs_trans_reserve_quota_nblks,
.qo_reserve_quota_bydquots = xfs_trans_reserve_quota_bydquots,
.qo_unreserve_and_mod_dquots = xfs_trans_unreserve_and_mod_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
......@@ -43,20 +43,20 @@
* This is used for two variables in XFS, one of which is a debug trace
* buffer index. They are not accessed via any other atomic operations
* so this is safe. All other atomic increments and decrements in XFS
* now use the linux built in functions.
* now use the Linux built-in functions.
*/
extern spinlock_t Atomic_spin;
extern spinlock_t xfs_atomic_spin;
static __inline__ int atomicIncWithWrap(int *ip, int val)
{
unsigned long flags;
int ret;
spin_lock_irqsave(&Atomic_spin, flags);
spin_lock_irqsave(&xfs_atomic_spin, flags);
ret = *ip;
(*ip)++;
if (*ip == val) *ip = 0;
spin_unlock_irqrestore(&Atomic_spin, flags);
spin_unlock_irqrestore(&xfs_atomic_spin, flags);
return ret;
}
......
/*
* 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
......@@ -55,7 +55,7 @@ assfail(char *a, char *f, int l)
BUG();
}
#if (defined(DEBUG) || defined(INDUCE_IO_ERRROR))
#if ((defined(DEBUG) || defined(INDUCE_IO_ERRROR)) && !defined(NO_WANT_RANDOM))
unsigned long
random(void)
......@@ -79,7 +79,7 @@ get_thread_id(void)
return current->pid;
}
#endif /* DEBUG */
#endif /* DEBUG || INDUCE_IO_ERRROR || !NO_WANT_RANDOM */
void
cmn_err(register int level, char *fmt, ...)
......
/*
* 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
......@@ -272,15 +272,3 @@ mrdemote(mrlock_t *mrp)
}
MRUNLOCK(mrp);
}
int
mrislocked_access(mrlock_t *mrp)
{
return(mrp->mr_count > 0);
}
int
mrislocked_update(mrlock_t *mrp)
{
return(mrp->mr_count < 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
......@@ -80,7 +80,9 @@ extern void mrlock_init(mrlock_t *, int type, char *name, long sequence);
extern void mrfree(mrlock_t *);
#define mrinit(mrp, name) mrlock_init(mrp, MRLOCK_BARRIER, name, -1)
#define mraccess(mrp) mraccessf(mrp, 0) /* grab for READ/ACCESS */
#define mrupdate(mrp) mrupdatef(mrp, 0) /* grab for WRITE/UPDATE */
#define mraccess(mrp) mraccessf(mrp, 0) /* grab for READ/ACCESS */
#define mrupdate(mrp) mrupdatef(mrp, 0) /* grab for WRITE/UPDATE */
#define mrislocked_access(mrp) ((mrp)->mr_count > 0)
#define mrislocked_update(mrp) ((mrp)->mr_count < 0)
#endif /* __XFS_SUPPORT_MRLOCK_H__ */
/*
* Copyright (c) 2000-2002 Silicon Graphics, Inc. All Rights Reserved.
* Copyright (c) 2000-2003 Silicon Graphics, Inc. All Rights Reserved.
* Portions Copyright (c) 2002 Christoph Hellwig. All Rights Reserved.
*
* This program is free software; you can redistribute it and/or modify it
......@@ -46,7 +46,6 @@
typedef struct semaphore mutex_t;
#define mutex_init(lock, type, name) sema_init(lock, 1)
#define init_mutex(ptr, type, name, sequence) sema_init(lock, 1)
#define mutex_destroy(lock) sema_init(lock, -99)
#define mutex_lock(lock, num) down(lock)
#define mutex_trylock(lock) (down_trylock(lock) ? 0 : 1)
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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