Commit 347c53dc authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'for-linus' of git://oss.sgi.com:8090/xfs/xfs-2.6

* 'for-linus' of git://oss.sgi.com:8090/xfs/xfs-2.6: (59 commits)
  [XFS] eagerly remove vmap mappings to avoid upsetting Xen
  [XFS] simplify validata_fields
  [XFS] no longer using io_vnode, as was remaining from 23 cherrypick
  [XFS] Remove STATIC which was missing from prior manual merge
  [XFS] Put back the QUEUE_ORDERED_NONE test in the barrier check.
  [XFS] Turn off XBF_ASYNC flag before re-reading superblock.
  [XFS] avoid race in sync_inodes() that can fail to write out all dirty data
  [XFS] This fix prevents bulkstat from spinning in an infinite loop.
  [XFS] simplify xfs_create/mknod/symlink prototype
  [XFS] avoid xfs_getattr in XFS_IOC_FSGETXATTR ioctl
  [XFS] get_bulkall() could return incorrect inode state
  [XFS] Kill unused IOMAP_EOF flag
  [XFS] fix when DMAPI mount option processing happens
  [XFS] ensure file size is logged on synchronous writes
  [XFS] growlock should be a mutex
  [XFS] replace some large xfs_log_priv.h macros by proper functions
  [XFS] kill struct bhv_vfs
  [XFS] move syncing related members from struct bhv_vfs to struct xfs_mount
  [XFS] kill the vfs_flags member in struct bhv_vfs
  [XFS] kill the vfs_fsid and vfs_altfsid members in struct bhv_vfs
  ...
parents 5c8e191e 7f015072
......@@ -49,7 +49,6 @@ xfs-y += xfs_alloc.o \
xfs_alloc_btree.o \
xfs_attr.o \
xfs_attr_leaf.o \
xfs_behavior.o \
xfs_bit.o \
xfs_bmap.o \
xfs_bmap_btree.o \
......@@ -108,13 +107,11 @@ xfs-y += $(addprefix $(XFS_LINUX)/, \
xfs_iops.o \
xfs_lrw.o \
xfs_super.o \
xfs_vfs.o \
xfs_vnode.o)
# Objects in support/
xfs-y += $(addprefix support/, \
debug.o \
move.o \
uuid.o)
xfs-$(CONFIG_XFS_TRACE) += support/ktrace.o
......
......@@ -37,6 +37,7 @@
#include "xfs_error.h"
#include "xfs_rw.h"
#include "xfs_iomap.h"
#include "xfs_vnodeops.h"
#include <linux/mpage.h>
#include <linux/pagevec.h>
#include <linux/writeback.h>
......@@ -139,9 +140,11 @@ xfs_destroy_ioend(
next = bh->b_private;
bh->b_end_io(bh, !ioend->io_error);
}
if (unlikely(ioend->io_error))
vn_ioerror(ioend->io_vnode, ioend->io_error, __FILE__,__LINE__);
vn_iowake(ioend->io_vnode);
if (unlikely(ioend->io_error)) {
vn_ioerror(XFS_I(ioend->io_inode), ioend->io_error,
__FILE__,__LINE__);
}
vn_iowake(XFS_I(ioend->io_inode));
mempool_free(ioend, xfs_ioend_pool);
}
......@@ -156,14 +159,10 @@ STATIC void
xfs_setfilesize(
xfs_ioend_t *ioend)
{
xfs_inode_t *ip;
xfs_inode_t *ip = XFS_I(ioend->io_inode);
xfs_fsize_t isize;
xfs_fsize_t bsize;
ip = xfs_vtoi(ioend->io_vnode);
if (!ip)
return;
ASSERT((ip->i_d.di_mode & S_IFMT) == S_IFREG);
ASSERT(ioend->io_type != IOMAP_READ);
......@@ -181,7 +180,7 @@ xfs_setfilesize(
ip->i_d.di_size = isize;
ip->i_update_core = 1;
ip->i_update_size = 1;
mark_inode_dirty_sync(vn_to_inode(ioend->io_vnode));
mark_inode_dirty_sync(ioend->io_inode);
}
xfs_iunlock(ip, XFS_ILOCK_EXCL);
......@@ -227,12 +226,12 @@ xfs_end_bio_unwritten(
{
xfs_ioend_t *ioend =
container_of(work, xfs_ioend_t, io_work);
bhv_vnode_t *vp = ioend->io_vnode;
xfs_off_t offset = ioend->io_offset;
size_t size = ioend->io_size;
if (likely(!ioend->io_error)) {
bhv_vop_bmap(vp, offset, size, BMAPI_UNWRITTEN, NULL, NULL);
xfs_bmap(XFS_I(ioend->io_inode), offset, size,
BMAPI_UNWRITTEN, NULL, NULL);
xfs_setfilesize(ioend);
}
xfs_destroy_ioend(ioend);
......@@ -275,10 +274,10 @@ xfs_alloc_ioend(
ioend->io_error = 0;
ioend->io_list = NULL;
ioend->io_type = type;
ioend->io_vnode = vn_from_inode(inode);
ioend->io_inode = inode;
ioend->io_buffer_head = NULL;
ioend->io_buffer_tail = NULL;
atomic_inc(&ioend->io_vnode->v_iocount);
atomic_inc(&XFS_I(ioend->io_inode)->i_iocount);
ioend->io_offset = 0;
ioend->io_size = 0;
......@@ -302,12 +301,13 @@ xfs_map_blocks(
xfs_iomap_t *mapp,
int flags)
{
bhv_vnode_t *vp = vn_from_inode(inode);
xfs_inode_t *ip = XFS_I(inode);
int error, nmaps = 1;
error = bhv_vop_bmap(vp, offset, count, flags, mapp, &nmaps);
error = xfs_bmap(ip, offset, count,
flags, mapp, &nmaps);
if (!error && (flags & (BMAPI_WRITE|BMAPI_ALLOCATE)))
VMODIFY(vp);
xfs_iflags_set(ip, XFS_IMODIFIED);
return -error;
}
......@@ -497,7 +497,7 @@ xfs_cancel_ioend(
unlock_buffer(bh);
} while ((bh = next_bh) != NULL);
vn_iowake(ioend->io_vnode);
vn_iowake(XFS_I(ioend->io_inode));
mempool_free(ioend, xfs_ioend_pool);
} while ((ioend = next) != NULL);
}
......@@ -1237,10 +1237,7 @@ xfs_vm_writepages(
struct address_space *mapping,
struct writeback_control *wbc)
{
struct bhv_vnode *vp = vn_from_inode(mapping->host);
if (VN_TRUNC(vp))
VUNTRUNCATE(vp);
xfs_iflags_clear(XFS_I(mapping->host), XFS_ITRUNCATED);
return generic_writepages(mapping, wbc);
}
......@@ -1317,7 +1314,6 @@ __xfs_get_blocks(
int direct,
bmapi_flags_t flags)
{
bhv_vnode_t *vp = vn_from_inode(inode);
xfs_iomap_t iomap;
xfs_off_t offset;
ssize_t size;
......@@ -1327,7 +1323,7 @@ __xfs_get_blocks(
offset = (xfs_off_t)iblock << inode->i_blkbits;
ASSERT(bh_result->b_size >= (1 << inode->i_blkbits));
size = bh_result->b_size;
error = bhv_vop_bmap(vp, offset, size,
error = xfs_bmap(XFS_I(inode), offset, size,
create ? flags : BMAPI_READ, &iomap, &niomap);
if (error)
return -error;
......@@ -1475,13 +1471,13 @@ xfs_vm_direct_IO(
{
struct file *file = iocb->ki_filp;
struct inode *inode = file->f_mapping->host;
bhv_vnode_t *vp = vn_from_inode(inode);
xfs_iomap_t iomap;
int maps = 1;
int error;
ssize_t ret;
error = bhv_vop_bmap(vp, offset, 0, BMAPI_DEVICE, &iomap, &maps);
error = xfs_bmap(XFS_I(inode), offset, 0,
BMAPI_DEVICE, &iomap, &maps);
if (error)
return -error;
......@@ -1527,12 +1523,13 @@ xfs_vm_bmap(
sector_t block)
{
struct inode *inode = (struct inode *)mapping->host;
bhv_vnode_t *vp = vn_from_inode(inode);
struct xfs_inode *ip = XFS_I(inode);
vn_trace_entry(vp, __FUNCTION__, (inst_t *)__return_address);
bhv_vop_rwlock(vp, VRWLOCK_READ);
bhv_vop_flush_pages(vp, (xfs_off_t)0, -1, 0, FI_REMAPF);
bhv_vop_rwunlock(vp, VRWLOCK_READ);
vn_trace_entry(XFS_I(inode), __FUNCTION__,
(inst_t *)__return_address);
xfs_rwlock(ip, VRWLOCK_READ);
xfs_flush_pages(ip, (xfs_off_t)0, -1, 0, FI_REMAPF);
xfs_rwunlock(ip, VRWLOCK_READ);
return generic_block_bmap(mapping, block, xfs_get_blocks);
}
......
......@@ -32,7 +32,7 @@ typedef struct xfs_ioend {
unsigned int io_type; /* delalloc / unwritten */
int io_error; /* I/O error code */
atomic_t io_remaining; /* hold count */
struct bhv_vnode *io_vnode; /* file being written to */
struct inode *io_inode; /* file being written to */
struct buffer_head *io_buffer_head;/* buffer linked list head */
struct buffer_head *io_buffer_tail;/* buffer linked list tail */
size_t io_size; /* size of the extent */
......
......@@ -187,6 +187,19 @@ free_address(
{
a_list_t *aentry;
#ifdef CONFIG_XEN
/*
* Xen needs to be able to make sure it can get an exclusive
* RO mapping of pages it wants to turn into a pagetable. If
* a newly allocated page is also still being vmap()ed by xfs,
* it will cause pagetable construction to fail. This is a
* quick workaround to always eagerly unmap pages so that Xen
* is happy.
*/
vunmap(addr);
return;
#endif
aentry = kmalloc(sizeof(a_list_t), GFP_NOWAIT);
if (likely(aentry)) {
spin_lock(&as_lock);
......@@ -997,7 +1010,18 @@ xfs_buf_iodone_work(
xfs_buf_t *bp =
container_of(work, xfs_buf_t, b_iodone_work);
if (bp->b_iodone)
/*
* We can get an EOPNOTSUPP to ordered writes. Here we clear the
* ordered flag and reissue them. Because we can't tell the higher
* layers directly that they should not issue ordered I/O anymore, they
* need to check if the ordered flag was cleared during I/O completion.
*/
if ((bp->b_error == EOPNOTSUPP) &&
(bp->b_flags & (XBF_ORDERED|XBF_ASYNC)) == (XBF_ORDERED|XBF_ASYNC)) {
XB_TRACE(bp, "ordered_retry", bp->b_iodone);
bp->b_flags &= ~XBF_ORDERED;
xfs_buf_iorequest(bp);
} else if (bp->b_iodone)
(*(bp->b_iodone))(bp);
else if (bp->b_flags & XBF_ASYNC)
xfs_buf_relse(bp);
......
......@@ -17,12 +17,18 @@
*/
#include "xfs.h"
#include "xfs_types.h"
#include "xfs_dmapi.h"
#include "xfs_inum.h"
#include "xfs_log.h"
#include "xfs_trans.h"
#include "xfs_sb.h"
#include "xfs_ag.h"
#include "xfs_dmapi.h"
#include "xfs_mount.h"
#include "xfs_export.h"
#include "xfs_vnodeops.h"
#include "xfs_bmap_btree.h"
#include "xfs_inode.h"
#include "xfs_vfsops.h"
static struct dentry dotdot = { .d_name.name = "..", .d_name.len = 2, };
......@@ -96,9 +102,7 @@ xfs_fs_encode_fh(
int len;
int is64 = 0;
#if XFS_BIG_INUMS
bhv_vfs_t *vfs = vfs_from_sb(inode->i_sb);
if (!(vfs->vfs_flag & VFS_32BITINODES)) {
if (!(XFS_M(inode->i_sb)->m_flags & XFS_MOUNT_SMALL_INUMS)) {
/* filesystem may contain 64bit inode numbers */
is64 = XFS_FILEID_TYPE_64FLAG;
}
......@@ -138,10 +142,9 @@ xfs_fs_get_dentry(
bhv_vnode_t *vp;
struct inode *inode;
struct dentry *result;
bhv_vfs_t *vfsp = vfs_from_sb(sb);
int error;
error = bhv_vfs_vget(vfsp, &vp, (fid_t *)data);
error = xfs_vget(XFS_M(sb), &vp, (fid_t *)data);
if (error || vp == NULL)
return ERR_PTR(-ESTALE) ;
......@@ -159,12 +162,11 @@ xfs_fs_get_parent(
struct dentry *child)
{
int error;
bhv_vnode_t *vp, *cvp;
bhv_vnode_t *cvp;
struct dentry *parent;
cvp = NULL;
vp = vn_from_inode(child->d_inode);
error = bhv_vop_lookup(vp, &dotdot, &cvp, 0, NULL, NULL);
error = xfs_lookup(XFS_I(child->d_inode), &dotdot, &cvp);
if (unlikely(error))
return ERR_PTR(-error);
......
......@@ -37,6 +37,7 @@
#include "xfs_error.h"
#include "xfs_rw.h"
#include "xfs_ioctl32.h"
#include "xfs_vnodeops.h"
#include <linux/dcache.h>
#include <linux/smp_lock.h>
......@@ -55,13 +56,12 @@ __xfs_file_read(
loff_t pos)
{
struct file *file = iocb->ki_filp;
bhv_vnode_t *vp = vn_from_inode(file->f_path.dentry->d_inode);
BUG_ON(iocb->ki_pos != pos);
if (unlikely(file->f_flags & O_DIRECT))
ioflags |= IO_ISDIRECT;
return bhv_vop_read(vp, iocb, iov, nr_segs, &iocb->ki_pos,
ioflags, NULL);
return xfs_read(XFS_I(file->f_path.dentry->d_inode), iocb, iov,
nr_segs, &iocb->ki_pos, ioflags);
}
STATIC ssize_t
......@@ -93,14 +93,12 @@ __xfs_file_write(
loff_t pos)
{
struct file *file = iocb->ki_filp;
struct inode *inode = file->f_mapping->host;
bhv_vnode_t *vp = vn_from_inode(inode);
BUG_ON(iocb->ki_pos != pos);
if (unlikely(file->f_flags & O_DIRECT))
ioflags |= IO_ISDIRECT;
return bhv_vop_write(vp, iocb, iov, nr_segs, &iocb->ki_pos,
ioflags, NULL);
return xfs_write(XFS_I(file->f_mapping->host), iocb, iov, nr_segs,
&iocb->ki_pos, ioflags);
}
STATIC ssize_t
......@@ -131,8 +129,8 @@ xfs_file_splice_read(
size_t len,
unsigned int flags)
{
return bhv_vop_splice_read(vn_from_inode(infilp->f_path.dentry->d_inode),
infilp, ppos, pipe, len, flags, 0, NULL);
return xfs_splice_read(XFS_I(infilp->f_path.dentry->d_inode),
infilp, ppos, pipe, len, flags, 0);
}
STATIC ssize_t
......@@ -143,9 +141,8 @@ xfs_file_splice_read_invis(
size_t len,
unsigned int flags)
{
return bhv_vop_splice_read(vn_from_inode(infilp->f_path.dentry->d_inode),
infilp, ppos, pipe, len, flags, IO_INVIS,
NULL);
return xfs_splice_read(XFS_I(infilp->f_path.dentry->d_inode),
infilp, ppos, pipe, len, flags, IO_INVIS);
}
STATIC ssize_t
......@@ -156,8 +153,8 @@ xfs_file_splice_write(
size_t len,
unsigned int flags)
{
return bhv_vop_splice_write(vn_from_inode(outfilp->f_path.dentry->d_inode),
pipe, outfilp, ppos, len, flags, 0, NULL);
return xfs_splice_write(XFS_I(outfilp->f_path.dentry->d_inode),
pipe, outfilp, ppos, len, flags, 0);
}
STATIC ssize_t
......@@ -168,9 +165,8 @@ xfs_file_splice_write_invis(
size_t len,
unsigned int flags)
{
return bhv_vop_splice_write(vn_from_inode(outfilp->f_path.dentry->d_inode),
pipe, outfilp, ppos, len, flags, IO_INVIS,
NULL);
return xfs_splice_write(XFS_I(outfilp->f_path.dentry->d_inode),
pipe, outfilp, ppos, len, flags, IO_INVIS);
}
STATIC int
......@@ -180,7 +176,7 @@ xfs_file_open(
{
if (!(filp->f_flags & O_LARGEFILE) && i_size_read(inode) > MAX_NON_LFS)
return -EFBIG;
return -bhv_vop_open(vn_from_inode(inode), NULL);
return -xfs_open(XFS_I(inode));
}
STATIC int
......@@ -188,11 +184,7 @@ xfs_file_release(
struct inode *inode,
struct file *filp)
{
bhv_vnode_t *vp = vn_from_inode(inode);
if (vp)
return -bhv_vop_release(vp);
return 0;
return -xfs_release(XFS_I(inode));
}
STATIC int
......@@ -201,14 +193,13 @@ xfs_file_fsync(
struct dentry *dentry,
int datasync)
{
bhv_vnode_t *vp = vn_from_inode(dentry->d_inode);
int flags = FSYNC_WAIT;
if (datasync)
flags |= FSYNC_DATA;
if (VN_TRUNC(vp))
VUNTRUNCATE(vp);
return -bhv_vop_fsync(vp, flags, NULL, (xfs_off_t)0, (xfs_off_t)-1);
xfs_iflags_clear(XFS_I(dentry->d_inode), XFS_ITRUNCATED);
return -xfs_fsync(XFS_I(dentry->d_inode), flags,
(xfs_off_t)0, (xfs_off_t)-1);
}
#ifdef CONFIG_XFS_DMAPI
......@@ -233,74 +224,30 @@ xfs_file_readdir(
void *dirent,
filldir_t filldir)
{
int error = 0;
bhv_vnode_t *vp = vn_from_inode(filp->f_path.dentry->d_inode);
uio_t uio;
iovec_t iov;
int eof = 0;
caddr_t read_buf;
int namelen, size = 0;
size_t rlen = PAGE_CACHE_SIZE;
xfs_off_t start_offset, curr_offset;
xfs_dirent_t *dbp = NULL;
/* Try fairly hard to get memory */
do {
if ((read_buf = kmalloc(rlen, GFP_KERNEL)))
break;
rlen >>= 1;
} while (rlen >= 1024);
if (read_buf == NULL)
return -ENOMEM;
uio.uio_iov = &iov;
uio.uio_segflg = UIO_SYSSPACE;
curr_offset = filp->f_pos;
if (filp->f_pos != 0x7fffffff)
uio.uio_offset = filp->f_pos;
else
uio.uio_offset = 0xffffffff;
while (!eof) {
uio.uio_resid = iov.iov_len = rlen;
iov.iov_base = read_buf;
uio.uio_iovcnt = 1;
start_offset = uio.uio_offset;
error = bhv_vop_readdir(vp, &uio, NULL, &eof);
if ((uio.uio_offset == start_offset) || error) {
size = 0;
break;
}
size = rlen - uio.uio_resid;
dbp = (xfs_dirent_t *)read_buf;
while (size > 0) {
namelen = strlen(dbp->d_name);
if (filldir(dirent, dbp->d_name, namelen,
(loff_t) curr_offset & 0x7fffffff,
(ino_t) dbp->d_ino,
DT_UNKNOWN)) {
goto done;
}
size -= dbp->d_reclen;
curr_offset = (loff_t)dbp->d_off /* & 0x7fffffff */;
dbp = (xfs_dirent_t *)((char *)dbp + dbp->d_reclen);
}
}
done:
if (!error) {
if (size == 0)
filp->f_pos = uio.uio_offset & 0x7fffffff;
else if (dbp)
filp->f_pos = curr_offset;
}
struct inode *inode = filp->f_path.dentry->d_inode;
xfs_inode_t *ip = XFS_I(inode);
int error;
size_t bufsize;
/*
* The Linux API doesn't pass down the total size of the buffer
* we read into down to the filesystem. With the filldir concept
* it's not needed for correct information, but the XFS dir2 leaf
* code wants an estimate of the buffer size to calculate it's
* readahead window and size the buffers used for mapping to
* physical blocks.
*
* Try to give it an estimate that's good enough, maybe at some
* point we can change the ->readdir prototype to include the
* buffer size.
*/
bufsize = (size_t)min_t(loff_t, PAGE_SIZE, inode->i_size);
kfree(read_buf);
return -error;
error = xfs_readdir(ip, dirent, bufsize,
(xfs_off_t *)&filp->f_pos, filldir);
if (error)
return -error;
return 0;
}
STATIC int
......@@ -312,7 +259,7 @@ xfs_file_mmap(
vma->vm_flags |= VM_CAN_NONLINEAR;
#ifdef CONFIG_XFS_DMAPI
if (vn_from_inode(filp->f_path.dentry->d_inode)->v_vfsp->vfs_flag & VFS_DMI)
if (XFS_M(filp->f_path.dentry->d_inode->i_sb)->m_flags & XFS_MOUNT_DMAPI)
vma->vm_ops = &xfs_dmapi_file_vm_ops;
#endif /* CONFIG_XFS_DMAPI */
......@@ -328,10 +275,9 @@ xfs_file_ioctl(
{
int error;
struct inode *inode = filp->f_path.dentry->d_inode;
bhv_vnode_t *vp = vn_from_inode(inode);
error = bhv_vop_ioctl(vp, inode, filp, 0, cmd, (void __user *)p);
VMODIFY(vp);
error = xfs_ioctl(XFS_I(inode), filp, 0, cmd, (void __user *)p);
xfs_iflags_set(XFS_I(inode), XFS_IMODIFIED);
/* NOTE: some of the ioctl's return positive #'s as a
* byte count indicating success, such as
......@@ -350,10 +296,9 @@ xfs_file_ioctl_invis(
{
int error;
struct inode *inode = filp->f_path.dentry->d_inode;
bhv_vnode_t *vp = vn_from_inode(inode);
error = bhv_vop_ioctl(vp, inode, filp, IO_INVIS, cmd, (void __user *)p);
VMODIFY(vp);
error = xfs_ioctl(XFS_I(inode), filp, IO_INVIS, cmd, (void __user *)p);
xfs_iflags_set(XFS_I(inode), XFS_IMODIFIED);
/* NOTE: some of the ioctl's return positive #'s as a
* byte count indicating success, such as
......@@ -371,16 +316,14 @@ xfs_vm_mprotect(
struct vm_area_struct *vma,
unsigned int newflags)
{
bhv_vnode_t *vp = vn_from_inode(vma->vm_file->f_path.dentry->d_inode);
struct inode *inode = vma->vm_file->f_path.dentry->d_inode;
struct xfs_mount *mp = XFS_M(inode->i_sb);
int error = 0;
if (vp->v_vfsp->vfs_flag & VFS_DMI) {
if (mp->m_flags & XFS_MOUNT_DMAPI) {
if ((vma->vm_flags & VM_MAYSHARE) &&
(newflags & VM_WRITE) && !(vma->vm_flags & VM_WRITE)) {
xfs_mount_t *mp = XFS_VFSTOM(vp->v_vfsp);
(newflags & VM_WRITE) && !(vma->vm_flags & VM_WRITE))
error = XFS_SEND_MMAP(mp, vma, VM_WRITE);
}
}
return error;
}
......@@ -397,18 +340,17 @@ STATIC int
xfs_file_open_exec(
struct inode *inode)
{
bhv_vnode_t *vp = vn_from_inode(inode);
struct xfs_mount *mp = XFS_M(inode->i_sb);
if (unlikely(vp->v_vfsp->vfs_flag & VFS_DMI)) {
xfs_mount_t *mp = XFS_VFSTOM(vp->v_vfsp);
xfs_inode_t *ip = xfs_vtoi(vp);
if (unlikely(mp->m_flags & XFS_MOUNT_DMAPI)) {
if (DM_EVENT_ENABLED(XFS_I(inode), DM_EVENT_READ)) {
bhv_vnode_t *vp = vn_from_inode(inode);
if (!ip)
return -EINVAL;
if (DM_EVENT_ENABLED(vp->v_vfsp, ip, DM_EVENT_READ))
return -XFS_SEND_DATA(mp, DM_EVENT_READ, vp,
0, 0, 0, NULL);
return -XFS_SEND_DATA(mp, DM_EVENT_READ,
vp, 0, 0, 0, NULL);
}
}
return 0;
}
#endif /* HAVE_FOP_OPEN_EXEC */
......
......@@ -16,66 +16,78 @@
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "xfs.h"
#include "xfs_vnodeops.h"
/*
* The following six includes are needed so that we can include
* xfs_inode.h. What a mess..
*/
#include "xfs_bmap_btree.h"
#include "xfs_inum.h"
#include "xfs_dir2.h"
#include "xfs_dir2_sf.h"
#include "xfs_attr_sf.h"
#include "xfs_dinode.h"
#include "xfs_inode.h"
int fs_noerr(void) { return 0; }
int fs_nosys(void) { return ENOSYS; }
void fs_noval(void) { return; }
void
fs_tosspages(
bhv_desc_t *bdp,
xfs_tosspages(
xfs_inode_t *ip,
xfs_off_t first,
xfs_off_t last,
int fiopt)
{
bhv_vnode_t *vp = BHV_TO_VNODE(bdp);
struct inode *ip = vn_to_inode(vp);
bhv_vnode_t *vp = XFS_ITOV(ip);
struct inode *inode = vn_to_inode(vp);
if (VN_CACHED(vp))
truncate_inode_pages(ip->i_mapping, first);
truncate_inode_pages(inode->i_mapping, first);
}
int
fs_flushinval_pages(
bhv_desc_t *bdp,
xfs_flushinval_pages(
xfs_inode_t *ip,
xfs_off_t first,
xfs_off_t last,
int fiopt)
{
bhv_vnode_t *vp = BHV_TO_VNODE(bdp);
struct inode *ip = vn_to_inode(vp);
bhv_vnode_t *vp = XFS_ITOV(ip);
struct inode *inode = vn_to_inode(vp);
int ret = 0;
if (VN_CACHED(vp)) {
if (VN_TRUNC(vp))
VUNTRUNCATE(vp);
ret = filemap_write_and_wait(ip->i_mapping);
xfs_iflags_clear(ip, XFS_ITRUNCATED);
ret = filemap_write_and_wait(inode->i_mapping);
if (!ret)
truncate_inode_pages(ip->i_mapping, first);
truncate_inode_pages(inode->i_mapping, first);
}
return ret;
}
int
fs_flush_pages(
bhv_desc_t *bdp,
xfs_flush_pages(
xfs_inode_t *ip,
xfs_off_t first,
xfs_off_t last,
uint64_t flags,
int fiopt)
{
bhv_vnode_t *vp = BHV_TO_VNODE(bdp);
struct inode *ip = vn_to_inode(vp);
bhv_vnode_t *vp = XFS_ITOV(ip);
struct inode *inode = vn_to_inode(vp);
int ret = 0;
int ret2;
if (VN_DIRTY(vp)) {
if (VN_TRUNC(vp))
VUNTRUNCATE(vp);
ret = filemap_fdatawrite(ip->i_mapping);
xfs_iflags_clear(ip, XFS_ITRUNCATED);
ret = filemap_fdatawrite(inode->i_mapping);
if (flags & XFS_B_ASYNC)
return ret;
ret2 = filemap_fdatawait(ip->i_mapping);
ret2 = filemap_fdatawait(inode->i_mapping);
if (!ret)
ret = ret2;
}
......
......@@ -18,12 +18,8 @@
#ifndef __XFS_FS_SUBR_H__
#define __XFS_FS_SUBR_H__
struct cred;
extern int fs_noerr(void);
extern int fs_nosys(void);
extern void fs_noval(void);
extern void fs_tosspages(bhv_desc_t *, xfs_off_t, xfs_off_t, int);
extern int fs_flushinval_pages(bhv_desc_t *, xfs_off_t, xfs_off_t, int);
extern int fs_flush_pages(bhv_desc_t *, xfs_off_t, xfs_off_t, uint64_t, int);
#endif /* __XFS_FS_SUBR_H__ */
......@@ -19,11 +19,6 @@
#include "xfs_cred.h"
#include "xfs_sysctl.h"
/*
* System memory size - used to scale certain data structures in XFS.
*/
unsigned long xfs_physmem;
/*
* Tunable XFS parameters. xfs_params is required even when CONFIG_SYSCTL=n,
* other XFS code uses these values. Times are measured in centisecs (i.e.
......
......@@ -19,7 +19,6 @@
#define __XFS_GLOBALS_H__
extern uint64_t xfs_panic_mask; /* set to cause more panics */
extern unsigned long xfs_physmem;
extern struct cred *sys_cred;
#endif /* __XFS_GLOBALS_H__ */
This diff is collapsed.
......@@ -43,6 +43,7 @@
#include "xfs_itable.h"
#include "xfs_error.h"
#include "xfs_dfrag.h"
#include "xfs_vnodeops.h"
#define _NATIVE_IOC(cmd, type) \
_IOC(_IOC_DIR(cmd), _IOC_TYPE(cmd), _IOC_NR(cmd), sizeof(type))
......@@ -370,7 +371,6 @@ xfs_compat_ioctl(
unsigned long arg)
{
struct inode *inode = file->f_path.dentry->d_inode;
bhv_vnode_t *vp = vn_from_inode(inode);
int error;
switch (cmd) {
......@@ -443,7 +443,7 @@ xfs_compat_ioctl(
case XFS_IOC_FSBULKSTAT_SINGLE_32:
case XFS_IOC_FSINUMBERS_32:
cmd = _NATIVE_IOC(cmd, struct xfs_fsop_bulkreq);
return xfs_ioc_bulkstat_compat(XFS_BHVTOI(VNHEAD(vp))->i_mount,
return xfs_ioc_bulkstat_compat(XFS_I(inode)->i_mount,
cmd, (void __user*)arg);
case XFS_IOC_FD_TO_HANDLE_32:
case XFS_IOC_PATH_TO_HANDLE_32:
......@@ -457,8 +457,8 @@ xfs_compat_ioctl(
return -ENOIOCTLCMD;
}
error = bhv_vop_ioctl(vp, inode, file, mode, cmd, (void __user *)arg);
VMODIFY(vp);
error = xfs_ioctl(XFS_I(inode), file, mode, cmd, (void __user *)arg);
xfs_iflags_set(XFS_I(inode), XFS_IMODIFIED);
return error;
}
......
This diff is collapsed.
......@@ -26,11 +26,15 @@ extern const struct file_operations xfs_file_operations;
extern const struct file_operations xfs_dir_file_operations;
extern const struct file_operations xfs_invis_file_operations;
extern int xfs_ioctl(struct bhv_desc *, struct inode *, struct file *,
int, unsigned int, void __user *);
struct xfs_inode;
extern void xfs_ichgtime(struct xfs_inode *, int);
extern void xfs_ichgtime_fast(struct xfs_inode *, struct inode *, int);
#define xfs_vtoi(vp) \
((struct xfs_inode *)vn_to_inode(vp)->i_private)
#define XFS_I(inode) \
((struct xfs_inode *)(inode)->i_private)
#endif /* __XFS_IOPS_H__ */
......@@ -51,7 +51,6 @@
#include <support/ktrace.h>
#include <support/debug.h>
#include <support/move.h>
#include <support/uuid.h>
#include <linux/mm.h>
......@@ -75,6 +74,7 @@
#include <linux/cpu.h>
#include <linux/notifier.h>
#include <linux/delay.h>
#include <linux/log2.h>
#include <asm/page.h>
#include <asm/div64.h>
......@@ -83,7 +83,6 @@
#include <asm/byteorder.h>
#include <asm/unaligned.h>
#include <xfs_behavior.h>
#include <xfs_vfs.h>
#include <xfs_cred.h>
#include <xfs_vnode.h>
......
......@@ -48,6 +48,7 @@
#include "xfs_buf_item.h"
#include "xfs_utils.h"
#include "xfs_iomap.h"
#include "xfs_vnodeops.h"
#include <linux/capability.h>
#include <linux/writeback.h>
......@@ -169,27 +170,22 @@ xfs_iozero(
ssize_t /* bytes read, or (-) error */
xfs_read(
bhv_desc_t *bdp,
xfs_inode_t *ip,
struct kiocb *iocb,
const struct iovec *iovp,
unsigned int segs,
loff_t *offset,
int ioflags,
cred_t *credp)
int ioflags)
{
struct file *file = iocb->ki_filp;
struct inode *inode = file->f_mapping->host;
bhv_vnode_t *vp = XFS_ITOV(ip);
xfs_mount_t *mp = ip->i_mount;
size_t size = 0;
ssize_t ret = 0;
xfs_fsize_t n;
xfs_inode_t *ip;
xfs_mount_t *mp;
bhv_vnode_t *vp;
unsigned long seg;
ip = XFS_BHVTOI(bdp);
vp = BHV_TO_VNODE(bdp);
mp = ip->i_mount;
XFS_STATS_INC(xs_read_calls);
......@@ -234,13 +230,11 @@ xfs_read(
mutex_lock(&inode->i_mutex);
xfs_ilock(ip, XFS_IOLOCK_SHARED);
if (DM_EVENT_ENABLED(vp->v_vfsp, ip, DM_EVENT_READ) &&
!(ioflags & IO_INVIS)) {
if (DM_EVENT_ENABLED(ip, DM_EVENT_READ) && !(ioflags & IO_INVIS)) {
bhv_vrwlock_t locktype = VRWLOCK_READ;
int dmflags = FILP_DELAY_FLAG(file) | DM_SEM_FLAG_RD(ioflags);
ret = -XFS_SEND_DATA(mp, DM_EVENT_READ,
BHV_TO_VNODE(bdp), *offset, size,
ret = -XFS_SEND_DATA(mp, DM_EVENT_READ, vp, *offset, size,
dmflags, &locktype);
if (ret) {
xfs_iunlock(ip, XFS_IOLOCK_SHARED);
......@@ -252,8 +246,9 @@ xfs_read(
if (unlikely(ioflags & IO_ISDIRECT)) {
if (VN_CACHED(vp))
ret = bhv_vop_flushinval_pages(vp, ctooff(offtoct(*offset)),
-1, FI_REMAPF_LOCKED);
ret = xfs_flushinval_pages(ip,
ctooff(offtoct(*offset)),
-1, FI_REMAPF_LOCKED);
mutex_unlock(&inode->i_mutex);
if (ret) {
xfs_iunlock(ip, XFS_IOLOCK_SHARED);
......@@ -277,16 +272,15 @@ xfs_read(
ssize_t
xfs_splice_read(
bhv_desc_t *bdp,
xfs_inode_t *ip,
struct file *infilp,
loff_t *ppos,
struct pipe_inode_info *pipe,
size_t count,
int flags,
int ioflags,
cred_t *credp)
int ioflags)
{
xfs_inode_t *ip = XFS_BHVTOI(bdp);
bhv_vnode_t *vp = XFS_ITOV(ip);
xfs_mount_t *mp = ip->i_mount;
ssize_t ret;
......@@ -296,13 +290,11 @@ xfs_splice_read(
xfs_ilock(ip, XFS_IOLOCK_SHARED);
if (DM_EVENT_ENABLED(BHV_TO_VNODE(bdp)->v_vfsp, ip, DM_EVENT_READ) &&
(!(ioflags & IO_INVIS))) {
if (DM_EVENT_ENABLED(ip, DM_EVENT_READ) && !(ioflags & IO_INVIS)) {
bhv_vrwlock_t locktype = VRWLOCK_READ;
int error;
error = XFS_SEND_DATA(mp, DM_EVENT_READ, BHV_TO_VNODE(bdp),
*ppos, count,
error = XFS_SEND_DATA(mp, DM_EVENT_READ, vp, *ppos, count,
FILP_DELAY_FLAG(infilp), &locktype);
if (error) {
xfs_iunlock(ip, XFS_IOLOCK_SHARED);
......@@ -321,16 +313,15 @@ xfs_splice_read(
ssize_t
xfs_splice_write(
bhv_desc_t *bdp,
xfs_inode_t *ip,
struct pipe_inode_info *pipe,
struct file *outfilp,
loff_t *ppos,
size_t count,
int flags,
int ioflags,
cred_t *credp)
int ioflags)
{
xfs_inode_t *ip = XFS_BHVTOI(bdp);
bhv_vnode_t *vp = XFS_ITOV(ip);
xfs_mount_t *mp = ip->i_mount;
xfs_iocore_t *io = &ip->i_iocore;
ssize_t ret;
......@@ -343,13 +334,11 @@ xfs_splice_write(
xfs_ilock(ip, XFS_IOLOCK_EXCL);
if (DM_EVENT_ENABLED(BHV_TO_VNODE(bdp)->v_vfsp, ip, DM_EVENT_WRITE) &&
(!(ioflags & IO_INVIS))) {
if (DM_EVENT_ENABLED(ip, DM_EVENT_WRITE) && !(ioflags & IO_INVIS)) {
bhv_vrwlock_t locktype = VRWLOCK_WRITE;
int error;
error = XFS_SEND_DATA(mp, DM_EVENT_WRITE, BHV_TO_VNODE(bdp),
*ppos, count,
error = XFS_SEND_DATA(mp, DM_EVENT_WRITE, vp, *ppos, count,
FILP_DELAY_FLAG(outfilp), &locktype);
if (error) {
xfs_iunlock(ip, XFS_IOLOCK_EXCL);
......@@ -583,24 +572,22 @@ xfs_zero_eof(
ssize_t /* bytes written, or (-) error */
xfs_write(
bhv_desc_t *bdp,
struct xfs_inode *xip,
struct kiocb *iocb,
const struct iovec *iovp,
unsigned int nsegs,
loff_t *offset,
int ioflags,
cred_t *credp)
int ioflags)
{
struct file *file = iocb->ki_filp;
struct address_space *mapping = file->f_mapping;
struct inode *inode = mapping->host;
bhv_vnode_t *vp = XFS_ITOV(xip);
unsigned long segs = nsegs;
xfs_inode_t *xip;
xfs_mount_t *mp;
ssize_t ret = 0, error = 0;
xfs_fsize_t isize, new_size;
xfs_iocore_t *io;
bhv_vnode_t *vp;
int iolock;
int eventsent = 0;
bhv_vrwlock_t locktype;
......@@ -610,9 +597,6 @@ xfs_write(
XFS_STATS_INC(xs_write_calls);
vp = BHV_TO_VNODE(bdp);
xip = XFS_BHVTOI(bdp);
error = generic_segment_checks(iovp, &segs, &ocount, VERIFY_READ);
if (error)
return error;
......@@ -626,7 +610,7 @@ xfs_write(
io = &xip->i_iocore;
mp = io->io_mount;
vfs_wait_for_freeze(vp->v_vfsp, SB_FREEZE_WRITE);
xfs_wait_for_freeze(mp, SB_FREEZE_WRITE);
if (XFS_FORCED_SHUTDOWN(mp))
return -EIO;
......@@ -653,7 +637,7 @@ xfs_write(
goto out_unlock_mutex;
}
if ((DM_EVENT_ENABLED(vp->v_vfsp, xip, DM_EVENT_WRITE) &&
if ((DM_EVENT_ENABLED(xip, DM_EVENT_WRITE) &&
!(ioflags & IO_INVIS) && !eventsent)) {
int dmflags = FILP_DELAY_FLAG(file);
......@@ -722,7 +706,7 @@ xfs_write(
*/
if (pos > xip->i_size) {
error = xfs_zero_eof(BHV_TO_VNODE(bdp), io, pos, xip->i_size);
error = xfs_zero_eof(vp, io, pos, xip->i_size);
if (error) {
xfs_iunlock(xip, XFS_ILOCK_EXCL);
goto out_unlock_internal;
......@@ -758,7 +742,8 @@ xfs_write(
WARN_ON(need_i_mutex == 0);
xfs_inval_cached_trace(io, pos, -1,
ctooff(offtoct(pos)), -1);
error = bhv_vop_flushinval_pages(vp, ctooff(offtoct(pos)),
error = xfs_flushinval_pages(xip,
ctooff(offtoct(pos)),
-1, FI_REMAPF_LOCKED);
if (error)
goto out_unlock_internal;
......@@ -805,11 +790,9 @@ xfs_write(
if (ret == -EIOCBQUEUED && !(ioflags & IO_ISAIO))
ret = wait_on_sync_kiocb(iocb);
if ((ret == -ENOSPC) &&
DM_EVENT_ENABLED(vp->v_vfsp, xip, DM_EVENT_NOSPACE) &&
!(ioflags & IO_INVIS)) {
xfs_rwunlock(bdp, locktype);
if (ret == -ENOSPC &&
DM_EVENT_ENABLED(xip, DM_EVENT_NOSPACE) && !(ioflags & IO_INVIS)) {
xfs_rwunlock(xip, locktype);
if (need_i_mutex)
mutex_unlock(&inode->i_mutex);
error = XFS_SEND_NAMESP(xip->i_mount, DM_EVENT_NOSPACE, vp,
......@@ -817,7 +800,7 @@ xfs_write(
0, 0, 0); /* Delay flag intentionally unused */
if (need_i_mutex)
mutex_lock(&inode->i_mutex);
xfs_rwlock(bdp, locktype);
xfs_rwlock(xip, locktype);
if (error)
goto out_unlock_internal;
pos = xip->i_size;
......@@ -844,20 +827,19 @@ xfs_write(
/* Handle various SYNC-type writes */
if ((file->f_flags & O_SYNC) || IS_SYNC(inode)) {
error = xfs_write_sync_logforce(mp, xip);
if (error)
goto out_unlock_internal;
xfs_rwunlock(bdp, locktype);
int error2;
xfs_rwunlock(xip, locktype);
if (need_i_mutex)
mutex_unlock(&inode->i_mutex);
error = sync_page_range(inode, mapping, pos, ret);
error2 = sync_page_range(inode, mapping, pos, ret);
if (!error)
error = -ret;
error = error2;
if (need_i_mutex)
mutex_lock(&inode->i_mutex);
xfs_rwlock(bdp, locktype);
xfs_rwlock(xip, locktype);
error2 = xfs_write_sync_logforce(mp, xip);
if (!error)
error = error2;
}
out_unlock_internal:
......@@ -875,7 +857,7 @@ xfs_write(
xip->i_d.di_size = xip->i_size;
xfs_iunlock(xip, XFS_ILOCK_EXCL);
}
xfs_rwunlock(bdp, locktype);
xfs_rwunlock(xip, locktype);
out_unlock_mutex:
if (need_i_mutex)
mutex_unlock(&inode->i_mutex);
......@@ -914,14 +896,14 @@ xfs_bdstrat_cb(struct xfs_buf *bp)
int
xfs_bmap(bhv_desc_t *bdp,
xfs_bmap(
xfs_inode_t *ip,
xfs_off_t offset,
ssize_t count,
int flags,
xfs_iomap_t *iomapp,
int *niomaps)
{
xfs_inode_t *ip = XFS_BHVTOI(bdp);
xfs_iocore_t *io = &ip->i_iocore;
ASSERT((ip->i_d.di_mode & S_IFMT) == S_IFREG);
......
......@@ -18,8 +18,6 @@
#ifndef __XFS_LRW_H__
#define __XFS_LRW_H__
struct bhv_desc;
struct bhv_vnode;
struct xfs_mount;
struct xfs_iocore;
struct xfs_inode;
......@@ -71,30 +69,11 @@ extern void xfs_inval_cached_trace(struct xfs_iocore *,
#define xfs_inval_cached_trace(io, offset, len, first, last)
#endif
/*
* Maximum count of bmaps used by read and write paths.
*/
#define XFS_MAX_RW_NBMAPS 4
extern int xfs_bmap(struct bhv_desc *, xfs_off_t, ssize_t, int,
struct xfs_iomap *, int *);
extern int xfsbdstrat(struct xfs_mount *, struct xfs_buf *);
extern int xfs_bdstrat_cb(struct xfs_buf *);
extern int xfs_dev_is_read_only(struct xfs_mount *, char *);
extern int xfs_zero_eof(struct bhv_vnode *, struct xfs_iocore *, xfs_off_t,
extern int xfs_zero_eof(struct inode *, struct xfs_iocore *, xfs_off_t,
xfs_fsize_t);
extern ssize_t xfs_read(struct bhv_desc *, struct kiocb *,
const struct iovec *, unsigned int,
loff_t *, int, struct cred *);
extern ssize_t xfs_write(struct bhv_desc *, struct kiocb *,
const struct iovec *, unsigned int,
loff_t *, int, struct cred *);
extern ssize_t xfs_splice_read(struct bhv_desc *, struct file *, loff_t *,
struct pipe_inode_info *, size_t, int, int,
struct cred *);
extern ssize_t xfs_splice_write(struct bhv_desc *, struct pipe_inode_info *,
struct file *, loff_t *, size_t, int, int,
struct cred *);
#endif /* __XFS_LRW_H__ */
This diff is collapsed.
......@@ -107,7 +107,8 @@ struct block_device;
extern __uint64_t xfs_max_file_offset(unsigned int);
extern void xfs_initialize_vnode(bhv_desc_t *, bhv_vnode_t *, bhv_desc_t *, int);
extern void xfs_initialize_vnode(struct xfs_mount *mp, bhv_vnode_t *vp,
struct xfs_inode *ip);
extern void xfs_flush_inode(struct xfs_inode *);
extern void xfs_flush_device(struct xfs_inode *);
......@@ -119,4 +120,6 @@ extern void xfs_blkdev_issue_flush(struct xfs_buftarg *);
extern struct export_operations xfs_export_operations;
#define XFS_M(sb) ((struct xfs_mount *)((sb)->s_fs_info))
#endif /* __XFS_SUPER_H__ */
/*
* Copyright (c) 2000-2005 Silicon Graphics, Inc.
* All Rights Reserved.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it would be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "xfs.h"
#include "xfs_fs.h"
#include "xfs_inum.h"
#include "xfs_log.h"
#include "xfs_clnt.h"
#include "xfs_trans.h"
#include "xfs_sb.h"
#include "xfs_ag.h"
#include "xfs_dir2.h"
#include "xfs_imap.h"
#include "xfs_alloc.h"
#include "xfs_dmapi.h"
#include "xfs_mount.h"
#include "xfs_quota.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_mntupdate(
struct bhv_desc *bdp,
int *fl,
struct xfs_mount_args *args)
{
struct bhv_desc *next = bdp;
ASSERT(next);
while (! (bhvtovfsops(next))->vfs_mntupdate)
next = BHV_NEXT(next);
return ((*bhvtovfsops(next)->vfs_mntupdate)(next, fl, args));
}
int
vfs_root(
struct bhv_desc *bdp,
struct bhv_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,
bhv_statvfs_t *statp,
struct bhv_vnode *vp)
{
struct bhv_desc *next = bdp;
ASSERT(next);
while (! (bhvtovfsops(next))->vfs_statvfs)
next = BHV_NEXT(next);
return ((*bhvtovfsops(next)->vfs_statvfs)(next, statp, 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 bhv_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 bhv_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));
}
void
vfs_freeze(
struct bhv_desc *bdp)
{
struct bhv_desc *next = bdp;
ASSERT(next);
while (! (bhvtovfsops(next))->vfs_freeze)
next = BHV_NEXT(next);
((*bhvtovfsops(next)->vfs_freeze)(next));
}
bhv_vfs_t *
vfs_allocate(
struct super_block *sb)
{
struct bhv_vfs *vfsp;
vfsp = kmem_zalloc(sizeof(bhv_vfs_t), KM_SLEEP);
bhv_head_init(VFS_BHVHEAD(vfsp), "vfs");
INIT_LIST_HEAD(&vfsp->vfs_sync_list);
spin_lock_init(&vfsp->vfs_sync_lock);
init_waitqueue_head(&vfsp->vfs_wait_single_sync_task);
vfsp->vfs_super = sb;
sb->s_fs_info = vfsp;
if (sb->s_flags & MS_RDONLY)
vfsp->vfs_flag |= VFS_RDONLY;
return vfsp;
}
bhv_vfs_t *
vfs_from_sb(
struct super_block *sb)
{
return (bhv_vfs_t *)sb->s_fs_info;
}
void
vfs_deallocate(
struct bhv_vfs *vfsp)
{
bhv_head_destroy(VFS_BHVHEAD(vfsp));
kmem_free(vfsp, sizeof(bhv_vfs_t));
}
void
vfs_insertops(
struct bhv_vfs *vfsp,
struct bhv_module_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 bhv_vfs *vfsp,
struct bhv_desc *bdp,
struct bhv_vfsops *vfsops,
void *mount)
{
bhv_desc_init(bdp, mount, vfsp, vfsops);
bhv_insert_initial(&vfsp->vfs_bh, bdp);
}
void
bhv_remove_vfsops(
struct bhv_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 bhv_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_VFSTOM(vfsp);
VFS_REMOVEBHV(vfsp, &mp->m_bhv);
xfs_mount_free(mp, 0);
}
void
bhv_insert_all_vfsops(
struct bhv_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);
}
......@@ -21,68 +21,25 @@
#include <linux/vfs.h>
#include "xfs_fs.h"
struct bhv_vfs;
struct bhv_vnode;
struct inode;
struct fid;
struct cred;
struct seq_file;
struct super_block;
struct xfs_inode;
struct xfs_mount;
struct xfs_mount_args;
typedef struct kstatfs bhv_statvfs_t;
typedef struct bhv_vfs_sync_work {
struct list_head w_list;
struct bhv_vfs *w_vfs;
struct xfs_mount *w_mount;
void *w_data; /* syncer routine argument */
void (*w_syncer)(struct bhv_vfs *, void *);
void (*w_syncer)(struct xfs_mount *, void *);
} bhv_vfs_sync_work_t;
typedef struct bhv_vfs {
u_int vfs_flag; /* flags */
xfs_fsid_t vfs_fsid; /* file system ID */
xfs_fsid_t *vfs_altfsid; /* An ID fixed for life of FS */
bhv_head_t vfs_bh; /* head of vfs behavior chain */
struct super_block *vfs_super; /* generic superblock pointer */
struct task_struct *vfs_sync_task; /* generalised sync thread */
bhv_vfs_sync_work_t vfs_sync_work; /* work item for VFS_SYNC */
struct list_head vfs_sync_list; /* sync thread work item list */
spinlock_t vfs_sync_lock; /* work item list lock */
int vfs_sync_seq; /* sync thread generation no. */
wait_queue_head_t vfs_wait_single_sync_task;
} bhv_vfs_t;
#define bhvtovfs(bdp) ( (struct bhv_vfs *)BHV_VOBJ(bdp) )
#define bhvtovfsops(bdp) ( (struct bhv_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 */
} bhv_vfs_type_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 */
/* ---- VFS_UMOUNT ---- 0x0008 -- unneeded, fixed via kthread APIs */
#define VFS_32BITINODES 0x0010 /* do not use inums above 32 bits */
#define VFS_END 0x0010 /* max flag */
#define SYNC_ATTR 0x0001 /* sync attributes */
#define SYNC_CLOSE 0x0002 /* close file system down */
#define SYNC_DELWRI 0x0004 /* look at delayed writes */
......@@ -115,118 +72,7 @@ typedef enum {
#define SHUTDOWN_REMOTE_REQ 0x0010 /* shutdown came from remote cell */
#define SHUTDOWN_DEVICE_REQ 0x0020 /* failed all paths to the device */
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_mntupdate_t)(bhv_desc_t *, int *,
struct xfs_mount_args *);
typedef int (*vfs_root_t)(bhv_desc_t *, struct bhv_vnode **);
typedef int (*vfs_statvfs_t)(bhv_desc_t *, bhv_statvfs_t *,
struct bhv_vnode *);
typedef int (*vfs_sync_t)(bhv_desc_t *, int, struct cred *);
typedef int (*vfs_vget_t)(bhv_desc_t *, struct bhv_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 bhv_vnode *, bhv_desc_t *, int);
typedef void (*vfs_force_shutdown_t)(bhv_desc_t *, int, char *, int);
typedef void (*vfs_freeze_t)(bhv_desc_t *);
typedef struct bhv_vfsops {
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_mntupdate_t vfs_mntupdate; /* update file system options */
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 */
vfs_freeze_t vfs_freeze; /* freeze fs for snapshot */
} bhv_vfsops_t;
/*
* Virtual filesystem operations, operating from head bhv.
*/
#define VFSHEAD(v) ((v)->vfs_bh.bh_first)
#define bhv_vfs_mount(v, ma,cr) vfs_mount(VFSHEAD(v), ma,cr)
#define bhv_vfs_parseargs(v, o,ma,f) vfs_parseargs(VFSHEAD(v), o,ma,f)
#define bhv_vfs_showargs(v, m) vfs_showargs(VFSHEAD(v), m)
#define bhv_vfs_unmount(v, f,cr) vfs_unmount(VFSHEAD(v), f,cr)
#define bhv_vfs_mntupdate(v, fl,args) vfs_mntupdate(VFSHEAD(v), fl,args)
#define bhv_vfs_root(v, vpp) vfs_root(VFSHEAD(v), vpp)
#define bhv_vfs_statvfs(v, sp,vp) vfs_statvfs(VFSHEAD(v), sp,vp)
#define bhv_vfs_sync(v, flag,cr) vfs_sync(VFSHEAD(v), flag,cr)
#define bhv_vfs_vget(v, vpp,fidp) vfs_vget(VFSHEAD(v), vpp,fidp)
#define bhv_vfs_dmapiops(v, p) vfs_dmapiops(VFSHEAD(v), p)
#define bhv_vfs_quotactl(v, c,id,p) vfs_quotactl(VFSHEAD(v), c,id,p)
#define bhv_vfs_init_vnode(v, vp,b,ul) vfs_init_vnode(VFSHEAD(v), vp,b,ul)
#define bhv_vfs_force_shutdown(v,u,f,l) vfs_force_shutdown(VFSHEAD(v), u,f,l)
#define bhv_vfs_freeze(v) vfs_freeze(VFSHEAD(v))
/*
* Virtual filesystem operations, operating from next bhv.
*/
#define bhv_next_vfs_mount(b, ma,cr) vfs_mount(b, ma,cr)
#define bhv_next_vfs_parseargs(b, o,ma,f) vfs_parseargs(b, o,ma,f)
#define bhv_next_vfs_showargs(b, m) vfs_showargs(b, m)
#define bhv_next_vfs_unmount(b, f,cr) vfs_unmount(b, f,cr)
#define bhv_next_vfs_mntupdate(b, fl,args) vfs_mntupdate(b, fl, args)
#define bhv_next_vfs_root(b, vpp) vfs_root(b, vpp)
#define bhv_next_vfs_statvfs(b, sp,vp) vfs_statvfs(b, sp,vp)
#define bhv_next_vfs_sync(b, flag,cr) vfs_sync(b, flag,cr)
#define bhv_next_vfs_vget(b, vpp,fidp) vfs_vget(b, vpp,fidp)
#define bhv_next_vfs_dmapiops(b, p) vfs_dmapiops(b, p)
#define bhv_next_vfs_quotactl(b, c,id,p) vfs_quotactl(b, c,id,p)
#define bhv_next_vfs_init_vnode(b, vp,b2,ul) vfs_init_vnode(b, vp,b2,ul)
#define bhv_next_force_shutdown(b, fl,f,l) vfs_force_shutdown(b, fl,f,l)
#define bhv_next_vfs_freeze(b) vfs_freeze(b)
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_mntupdate(bhv_desc_t *, int *, struct xfs_mount_args *);
extern int vfs_root(bhv_desc_t *, struct bhv_vnode **);
extern int vfs_statvfs(bhv_desc_t *, bhv_statvfs_t *, struct bhv_vnode *);
extern int vfs_sync(bhv_desc_t *, int, struct cred *);
extern int vfs_vget(bhv_desc_t *, struct bhv_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 bhv_vnode *, bhv_desc_t *, int);
extern void vfs_force_shutdown(bhv_desc_t *, int, char *, int);
extern void vfs_freeze(bhv_desc_t *);
#define vfs_test_for_freeze(vfs) ((vfs)->vfs_super->s_frozen)
#define vfs_wait_for_freeze(vfs,l) vfs_check_frozen((vfs)->vfs_super, (l))
typedef struct bhv_module_vfsops {
struct bhv_vfsops bhv_common;
void * bhv_custom;
} bhv_module_vfsops_t;
#define vfs_bhv_lookup(v, id) (bhv_lookup_range(&(v)->vfs_bh, (id), (id)))
#define vfs_bhv_custom(b) (((bhv_module_vfsops_t*)BHV_OPS(b))->bhv_custom)
#define vfs_bhv_set_custom(b,o) ((b)->bhv_custom = (void *)(o))
#define vfs_bhv_clr_custom(b) ((b)->bhv_custom = NULL)
extern bhv_vfs_t *vfs_allocate(struct super_block *);
extern bhv_vfs_t *vfs_from_sb(struct super_block *);
extern void vfs_deallocate(bhv_vfs_t *);
extern void vfs_insertbhv(bhv_vfs_t *, bhv_desc_t *, bhv_vfsops_t *, void *);
extern void vfs_insertops(bhv_vfs_t *, bhv_module_vfsops_t *);
extern void bhv_insert_all_vfsops(struct bhv_vfs *);
extern void bhv_remove_all_vfsops(struct bhv_vfs *, int);
extern void bhv_remove_vfsops(struct bhv_vfs *, int);
#define xfs_test_for_freeze(mp) ((mp)->m_super->s_frozen)
#define xfs_wait_for_freeze(mp,l) vfs_check_frozen((mp)->m_super, (l))
#endif /* __XFS_VFS_H__ */
......@@ -16,9 +16,21 @@
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "xfs.h"
#include "xfs_vnodeops.h"
#include "xfs_bmap_btree.h"
#include "xfs_inode.h"
/*
* And this gunk is needed for xfs_mount.h"
*/
#include "xfs_log.h"
#include "xfs_trans.h"
#include "xfs_sb.h"
#include "xfs_dmapi.h"
#include "xfs_inum.h"
#include "xfs_ag.h"
#include "xfs_mount.h"
uint64_t vn_generation; /* vnode generation number */
DEFINE_SPINLOCK(vnumber_lock);
/*
* Dedicated vnode inactive/reclaim sync semaphores.
......@@ -39,19 +51,19 @@ vn_init(void)
void
vn_iowait(
bhv_vnode_t *vp)
xfs_inode_t *ip)
{
wait_queue_head_t *wq = vptosync(vp);
wait_queue_head_t *wq = vptosync(ip);
wait_event(*wq, (atomic_read(&vp->v_iocount) == 0));
wait_event(*wq, (atomic_read(&ip->i_iocount) == 0));
}
void
vn_iowake(
bhv_vnode_t *vp)
xfs_inode_t *ip)
{
if (atomic_dec_and_test(&vp->v_iocount))
wake_up(vptosync(vp));
if (atomic_dec_and_test(&ip->i_iocount))
wake_up(vptosync(ip));
}
/*
......@@ -61,13 +73,13 @@ vn_iowake(
*/
void
vn_ioerror(
bhv_vnode_t *vp,
xfs_inode_t *ip,
int error,
char *f,
int l)
{
if (unlikely(error == -ENODEV))
bhv_vfs_force_shutdown(vp->v_vfsp, SHUTDOWN_DEVICE_REQ, f, l);
xfs_do_force_shutdown(ip->i_mount, SHUTDOWN_DEVICE_REQ, f, l);
}
bhv_vnode_t *
......@@ -79,27 +91,8 @@ vn_initialize(
XFS_STATS_INC(vn_active);
XFS_STATS_INC(vn_alloc);
vp->v_flag = VMODIFIED;
spinlock_init(&vp->v_lock, "v_lock");
spin_lock(&vnumber_lock);
if (!++vn_generation) /* v_number shouldn't be zero */
vn_generation++;
vp->v_number = vn_generation;
spin_unlock(&vnumber_lock);
ASSERT(VN_CACHED(vp) == 0);
/* Initialize the first behavior and the behavior chain head. */
vn_bhv_head_init(VN_BHV_HEAD(vp), "vnode");
atomic_set(&vp->v_iocount, 0);
#ifdef XFS_VNODE_TRACE
vp->v_trace = ktrace_alloc(VNODE_TRACE_SIZE, KM_SLEEP);
#endif /* XFS_VNODE_TRACE */
vn_trace_exit(vp, __FUNCTION__, (inst_t *)__return_address);
return vp;
}
......@@ -150,12 +143,12 @@ __vn_revalidate(
{
int error;
vn_trace_entry(vp, __FUNCTION__, (inst_t *)__return_address);
vn_trace_entry(xfs_vtoi(vp), __FUNCTION__, (inst_t *)__return_address);
vattr->va_mask = XFS_AT_STAT | XFS_AT_XFLAGS;
error = bhv_vop_getattr(vp, vattr, 0, NULL);
error = xfs_getattr(xfs_vtoi(vp), vattr, 0);
if (likely(!error)) {
vn_revalidate_core(vp, vattr);
VUNMODIFY(vp);
xfs_iflags_clear(xfs_vtoi(vp), XFS_IMODIFIED);
}
return -error;
}
......@@ -180,24 +173,35 @@ vn_hold(
XFS_STATS_INC(vn_hold);
VN_LOCK(vp);
inode = igrab(vn_to_inode(vp));
ASSERT(inode);
VN_UNLOCK(vp, 0);
return vp;
}
#ifdef XFS_VNODE_TRACE
#define KTRACE_ENTER(vp, vk, s, line, ra) \
ktrace_enter( (vp)->v_trace, \
/*
* Reference count of Linux inode if present, -1 if the xfs_inode
* has no associated Linux inode.
*/
static inline int xfs_icount(struct xfs_inode *ip)
{
bhv_vnode_t *vp = XFS_ITOV_NULL(ip);
if (vp)
return vn_count(vp);
return -1;
}
#define KTRACE_ENTER(ip, vk, s, line, ra) \
ktrace_enter( (ip)->i_trace, \
/* 0 */ (void *)(__psint_t)(vk), \
/* 1 */ (void *)(s), \
/* 2 */ (void *)(__psint_t) line, \
/* 3 */ (void *)(__psint_t)(vn_count(vp)), \
/* 3 */ (void *)(__psint_t)xfs_icount(ip), \
/* 4 */ (void *)(ra), \
/* 5 */ (void *)(__psunsigned_t)(vp)->v_flag, \
/* 5 */ NULL, \
/* 6 */ (void *)(__psint_t)current_cpu(), \
/* 7 */ (void *)(__psint_t)current_pid(), \
/* 8 */ (void *)__return_address, \
......@@ -207,32 +211,32 @@ vn_hold(
* Vnode tracing code.
*/
void
vn_trace_entry(bhv_vnode_t *vp, const char *func, inst_t *ra)
vn_trace_entry(xfs_inode_t *ip, const char *func, inst_t *ra)
{
KTRACE_ENTER(vp, VNODE_KTRACE_ENTRY, func, 0, ra);
KTRACE_ENTER(ip, VNODE_KTRACE_ENTRY, func, 0, ra);
}
void
vn_trace_exit(bhv_vnode_t *vp, const char *func, inst_t *ra)
vn_trace_exit(xfs_inode_t *ip, const char *func, inst_t *ra)
{
KTRACE_ENTER(vp, VNODE_KTRACE_EXIT, func, 0, ra);
KTRACE_ENTER(ip, VNODE_KTRACE_EXIT, func, 0, ra);
}
void
vn_trace_hold(bhv_vnode_t *vp, char *file, int line, inst_t *ra)
vn_trace_hold(xfs_inode_t *ip, char *file, int line, inst_t *ra)
{
KTRACE_ENTER(vp, VNODE_KTRACE_HOLD, file, line, ra);
KTRACE_ENTER(ip, VNODE_KTRACE_HOLD, file, line, ra);
}
void
vn_trace_ref(bhv_vnode_t *vp, char *file, int line, inst_t *ra)
vn_trace_ref(xfs_inode_t *ip, char *file, int line, inst_t *ra)
{
KTRACE_ENTER(vp, VNODE_KTRACE_REF, file, line, ra);
KTRACE_ENTER(ip, VNODE_KTRACE_REF, file, line, ra);
}
void
vn_trace_rele(bhv_vnode_t *vp, char *file, int line, inst_t *ra)
vn_trace_rele(xfs_inode_t *ip, char *file, int line, inst_t *ra)
{
KTRACE_ENTER(vp, VNODE_KTRACE_RELE, file, line, ra);
KTRACE_ENTER(ip, VNODE_KTRACE_RELE, file, line, ra);
}
#endif /* XFS_VNODE_TRACE */
This diff is collapsed.
......@@ -287,45 +287,6 @@ xfs_qm_rele_quotafs_ref(
XFS_QM_UNLOCK(xfs_Gqm);
}
/*
* This is called at mount time from xfs_mountfs to initialize the quotainfo
* structure and start the global quota manager (xfs_Gqm) if it hasn't done
* so already. Note that the superblock has not been read in yet.
*/
void
xfs_qm_mount_quotainit(
xfs_mount_t *mp,
uint flags)
{
/*
* User, projects or group quotas has to be on.
*/
ASSERT(flags & (XFSMNT_UQUOTA | XFSMNT_PQUOTA | XFSMNT_GQUOTA));
/*
* Initialize the flags in the mount structure. From this point
* onwards we look at m_qflags to figure out if quotas's ON/OFF, etc.
* Note that we enforce nothing if accounting is off.
* ie. XFSMNT_*QUOTA must be ON for XFSMNT_*QUOTAENF.
* It isn't necessary to take the quotaoff lock to do this; this is
* called from mount.
*/
if (flags & XFSMNT_UQUOTA) {
mp->m_qflags |= (XFS_UQUOTA_ACCT | XFS_UQUOTA_ACTIVE);
if (flags & XFSMNT_UQUOTAENF)
mp->m_qflags |= XFS_UQUOTA_ENFD;
}
if (flags & XFSMNT_GQUOTA) {
mp->m_qflags |= (XFS_GQUOTA_ACCT | XFS_GQUOTA_ACTIVE);
if (flags & XFSMNT_GQUOTAENF)
mp->m_qflags |= XFS_OQUOTA_ENFD;
} else if (flags & XFSMNT_PQUOTA) {
mp->m_qflags |= (XFS_PQUOTA_ACCT | XFS_PQUOTA_ACTIVE);
if (flags & XFSMNT_PQUOTAENF)
mp->m_qflags |= XFS_OQUOTA_ENFD;
}
}
/*
* Just destroy the quotainfo structure.
*/
......@@ -1039,7 +1000,7 @@ xfs_qm_dqdetach(
int
xfs_qm_sync(
xfs_mount_t *mp,
short flags)
int flags)
{
int recl, restarts;
xfs_dquot_t *dqp;
......@@ -1717,7 +1678,6 @@ xfs_qm_get_rtblks(
xfs_extnum_t idx; /* extent record index */
xfs_ifork_t *ifp; /* inode fork pointer */
xfs_extnum_t nextents; /* number of extent entries */
xfs_bmbt_rec_t *ep; /* pointer to an extent entry */
int error;
ASSERT(XFS_IS_REALTIME_INODE(ip));
......@@ -1728,10 +1688,8 @@ xfs_qm_get_rtblks(
}
rtblks = 0;
nextents = ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t);
for (idx = 0; idx < nextents; idx++) {
ep = xfs_iext_get_ext(ifp, idx);
rtblks += xfs_bmbt_get_blockcount(ep);
}
for (idx = 0; idx < nextents; idx++)
rtblks += xfs_bmbt_get_blockcount(xfs_iext_get_ext(ifp, idx));
*O_rtblks = (xfs_qcnt_t)rtblks;
return 0;
}
......@@ -2459,8 +2417,7 @@ xfs_qm_vop_dqalloc(
lockflags = XFS_ILOCK_EXCL;
xfs_ilock(ip, lockflags);
if ((flags & XFS_QMOPT_INHERIT) &&
XFS_INHERIT_GID(ip, XFS_MTOVFS(mp)))
if ((flags & XFS_QMOPT_INHERIT) && XFS_INHERIT_GID(ip))
gid = ip->i_d.di_gid;
/*
......
......@@ -166,12 +166,11 @@ typedef struct xfs_dquot_acct {
extern void xfs_qm_destroy_quotainfo(xfs_mount_t *);
extern int xfs_qm_mount_quotas(xfs_mount_t *, int);
extern void xfs_qm_mount_quotainit(xfs_mount_t *, uint);
extern int xfs_qm_quotacheck(xfs_mount_t *);
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);
extern int xfs_qm_sync(xfs_mount_t *, int);
/* dquot stuff */
extern boolean_t xfs_qm_dqalloc_incore(xfs_dquot_t **);
......@@ -199,7 +198,8 @@ extern void xfs_qm_freelist_unlink(xfs_dquot_t *);
extern int xfs_qm_freelist_lock_nowait(xfs_qm_t *);
/* system call interface */
extern int xfs_qm_quotactl(bhv_desc_t *, int, int, xfs_caddr_t);
extern int xfs_qm_quotactl(struct xfs_mount *, int, int,
xfs_caddr_t);
#ifdef DEBUG
extern int xfs_qm_internalqcheck(xfs_mount_t *);
......
......@@ -48,172 +48,13 @@
#include "xfs_buf_item.h"
#include "xfs_qm.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_PRJQUOTA "prjquota" /* project quota enabled */
#define MNTOPT_UQUOTA "uquota" /* user quota (IRIX variant) */
#define MNTOPT_GQUOTA "gquota" /* group quota (IRIX variant) */
#define MNTOPT_PQUOTA "pquota" /* project quota (IRIX variant) */
#define MNTOPT_UQUOTANOENF "uqnoenforce"/* user quota limit enforcement */
#define MNTOPT_GQUOTANOENF "gqnoenforce"/* group quota limit enforcement */
#define MNTOPT_PQUOTANOENF "pqnoenforce"/* project 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_PQUOTA) ||
!strcmp(this_char, MNTOPT_PRJQUOTA)) {
args->flags |= XFSMNT_PQUOTA | XFSMNT_PQUOTAENF;
referenced = 1;
} else if (!strcmp(this_char, MNTOPT_PQUOTANOENF)) {
args->flags |= XFSMNT_PQUOTA;
args->flags &= ~XFSMNT_PQUOTAENF;
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++ = ',';
}
if ((args->flags & XFSMNT_GQUOTA) && (args->flags & XFSMNT_PQUOTA)) {
cmn_err(CE_WARN,
"XFS: cannot mount with both project and group quota");
return XFS_ERROR(EINVAL);
}
error = bhv_next_vfs_parseargs(BHV_NEXT(bhv), options, args, update);
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 bhv_vfs *vfsp = bhvtovfs(bhv);
struct xfs_mount *mp = XFS_VFSTOM(vfsp);
if (mp->m_qflags & XFS_UQUOTA_ACCT) {
(mp->m_qflags & XFS_UQUOTA_ENFD) ?
seq_puts(m, "," MNTOPT_USRQUOTA) :
seq_puts(m, "," MNTOPT_UQUOTANOENF);
}
if (mp->m_qflags & XFS_PQUOTA_ACCT) {
(mp->m_qflags & XFS_OQUOTA_ENFD) ?
seq_puts(m, "," MNTOPT_PRJQUOTA) :
seq_puts(m, "," MNTOPT_PQUOTANOENF);
}
if (mp->m_qflags & XFS_GQUOTA_ACCT) {
(mp->m_qflags & XFS_OQUOTA_ENFD) ?
seq_puts(m, "," MNTOPT_GRPQUOTA) :
seq_puts(m, "," MNTOPT_GQUOTANOENF);
}
if (!(mp->m_qflags & XFS_ALL_QUOTA_ACCT))
seq_puts(m, "," MNTOPT_NOQUOTA);
return bhv_next_vfs_showargs(BHV_NEXT(bhv), m);
}
STATIC int
xfs_qm_mount(
struct bhv_desc *bhv,
struct xfs_mount_args *args,
struct cred *cr)
{
struct bhv_vfs *vfsp = bhvtovfs(bhv);
struct xfs_mount *mp = XFS_VFSTOM(vfsp);
if (args->flags & (XFSMNT_UQUOTA | XFSMNT_GQUOTA | XFSMNT_PQUOTA))
xfs_qm_mount_quotainit(mp, args->flags);
return bhv_next_vfs_mount(BHV_NEXT(bhv), args, cr);
}
/*
* Directory tree accounting is implemented using project quotas, where
* the project identifier is inherited from parent directories.
* A statvfs (df, etc.) of a directory that is using project quota should
* return a statvfs of the project, not the entire filesystem.
* This makes such trees appear as if they are filesystems in themselves.
*/
STATIC int
xfs_qm_statvfs(
struct bhv_desc *bhv,
STATIC void
xfs_fill_statvfs_from_dquot(
bhv_statvfs_t *statp,
struct bhv_vnode *vnode)
xfs_disk_dquot_t *dp)
{
xfs_mount_t *mp;
xfs_inode_t *ip;
xfs_dquot_t *dqp;
xfs_disk_dquot_t *dp;
__uint64_t limit;
int error;
error = bhv_next_vfs_statvfs(BHV_NEXT(bhv), statp, vnode);
if (error || !vnode)
return error;
mp = xfs_vfstom(bhvtovfs(bhv));
ip = xfs_vtoi(vnode);
if (!(ip->i_d.di_flags & XFS_DIFLAG_PROJINHERIT))
return 0;
if (!(mp->m_qflags & XFS_PQUOTA_ACCT))
return 0;
if (!(mp->m_qflags & XFS_OQUOTA_ENFD))
return 0;
if (xfs_qm_dqget(mp, NULL, ip->i_d.di_projid, XFS_DQ_PROJ, 0, &dqp))
return 0;
dp = &dqp->q_core;
limit = dp->d_blk_softlimit ?
be64_to_cpu(dp->d_blk_softlimit) :
......@@ -234,37 +75,35 @@ xfs_qm_statvfs(
(statp->f_files > be64_to_cpu(dp->d_icount)) ?
(statp->f_ffree - be64_to_cpu(dp->d_icount)) : 0;
}
xfs_qm_dqput(dqp);
return 0;
}
STATIC int
xfs_qm_syncall(
struct bhv_desc *bhv,
int flags,
cred_t *credp)
/*
* Directory tree accounting is implemented using project quotas, where
* the project identifier is inherited from parent directories.
* A statvfs (df, etc.) of a directory that is using project quota should
* return a statvfs of the project, not the entire filesystem.
* This makes such trees appear as if they are filesystems in themselves.
*/
STATIC void
xfs_qm_statvfs(
xfs_inode_t *ip,
bhv_statvfs_t *statp)
{
struct bhv_vfs *vfsp = bhvtovfs(bhv);
struct xfs_mount *mp = XFS_VFSTOM(vfsp);
int error;
xfs_mount_t *mp = ip->i_mount;
xfs_dquot_t *dqp;
/*
* 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);
}
}
if (!(ip->i_d.di_flags & XFS_DIFLAG_PROJINHERIT) ||
!((mp->m_qflags & (XFS_PQUOTA_ACCT|XFS_OQUOTA_ENFD))) ==
(XFS_PQUOTA_ACCT|XFS_OQUOTA_ENFD))
return;
if (!xfs_qm_dqget(mp, NULL, ip->i_d.di_projid, XFS_DQ_PROJ, 0, &dqp)) {
xfs_disk_dquot_t *dp = &dqp->q_core;
xfs_fill_statvfs_from_dquot(statp, dp);
xfs_qm_dqput(dqp);
}
return bhv_next_vfs_sync(BHV_NEXT(bhv), flags, credp);
}
STATIC int
......@@ -382,7 +221,7 @@ xfs_qm_dqrele_null(
}
static struct xfs_qmops xfs_qmcore_xfs = {
struct xfs_qmops xfs_qmcore_xfs = {
.xfs_qminit = xfs_qm_newmount,
.xfs_qmdone = xfs_qm_unmount_quotadestroy,
.xfs_qmmount = xfs_qm_endmount,
......@@ -396,36 +235,24 @@ static struct xfs_qmops xfs_qmcore_xfs = {
.xfs_dqvoprename = xfs_qm_vop_rename_dqattach,
.xfs_dqvopchown = xfs_qm_vop_chown,
.xfs_dqvopchownresv = xfs_qm_vop_chown_reserve,
.xfs_dqstatvfs = xfs_qm_statvfs,
.xfs_dqsync = xfs_qm_sync,
.xfs_quotactl = xfs_qm_quotactl,
.xfs_dqtrxops = &xfs_trans_dquot_ops,
};
struct bhv_module_vfsops xfs_qmops = { {
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_statvfs = xfs_qm_statvfs,
.vfs_sync = xfs_qm_syncall,
.vfs_quotactl = xfs_qm_quotactl, },
};
EXPORT_SYMBOL(xfs_qmcore_xfs);
void __init
xfs_qm_init(void)
{
static char message[] __initdata =
KERN_INFO "SGI XFS Quota Management subsystem\n";
printk(message);
printk(KERN_INFO "SGI XFS Quota Management subsystem\n");
mutex_init(&xfs_Gqm_lock);
vfs_bhv_set_custom(&xfs_qmops, &xfs_qmcore_xfs);
xfs_qm_init_procfs();
}
void __exit
xfs_qm_exit(void)
{
vfs_bhv_clr_custom(&xfs_qmops);
xfs_qm_cleanup_procfs();
if (qm_dqzone)
kmem_zone_destroy(qm_dqzone);
......
......@@ -81,18 +81,13 @@ STATIC void xfs_qm_export_dquot(xfs_mount_t *, xfs_disk_dquot_t *,
*/
int
xfs_qm_quotactl(
struct bhv_desc *bdp,
xfs_mount_t *mp,
int cmd,
int id,
xfs_caddr_t addr)
{
xfs_mount_t *mp;
bhv_vfs_t *vfsp;
int error;
vfsp = bhvtovfs(bdp);
mp = XFS_VFSTOM(vfsp);
ASSERT(addr != NULL || cmd == Q_XQUOTASYNC);
/*
......@@ -105,7 +100,7 @@ xfs_qm_quotactl(
*/
if (XFS_IS_QUOTA_ON(mp))
return XFS_ERROR(EINVAL);
if (vfsp->vfs_flag & VFS_RDONLY)
if (mp->m_flags & XFS_MOUNT_RDONLY)
return XFS_ERROR(EROFS);
return (xfs_qm_scall_trunc_qfiles(mp,
xfs_qm_import_qtype_flags(*(uint *)addr)));
......@@ -121,13 +116,13 @@ xfs_qm_quotactl(
* QUOTAON - enabling quota enforcement.
* Quota accounting must be turned on at mount time.
*/
if (vfsp->vfs_flag & VFS_RDONLY)
if (mp->m_flags & XFS_MOUNT_RDONLY)
return XFS_ERROR(EROFS);
return (xfs_qm_scall_quotaon(mp,
xfs_qm_import_flags(*(uint *)addr)));
case Q_XQUOTAOFF:
if (vfsp->vfs_flag & VFS_RDONLY)
if (mp->m_flags & XFS_MOUNT_RDONLY)
return XFS_ERROR(EROFS);
break;
......@@ -143,7 +138,7 @@ xfs_qm_quotactl(
switch (cmd) {
case Q_XQUOTAOFF:
if (vfsp->vfs_flag & VFS_RDONLY)
if (mp->m_flags & XFS_MOUNT_RDONLY)
return XFS_ERROR(EROFS);
error = xfs_qm_scall_quotaoff(mp,
xfs_qm_import_flags(*(uint *)addr),
......@@ -164,19 +159,19 @@ xfs_qm_quotactl(
break;
case Q_XSETQLIM:
if (vfsp->vfs_flag & VFS_RDONLY)
if (mp->m_flags & XFS_MOUNT_RDONLY)
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)
if (mp->m_flags & XFS_MOUNT_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_XSETPQLIM:
if (vfsp->vfs_flag & VFS_RDONLY)
if (mp->m_flags & XFS_MOUNT_RDONLY)
return XFS_ERROR(EROFS);
error = xfs_qm_scall_setqlim(mp, (xfs_dqid_t)id, XFS_DQ_PROJ,
(fs_disk_quota_t *)addr);
......
/*
* Copyright (c) 2000-2003,2005 Silicon Graphics, Inc.
* All Rights Reserved.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it would be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <xfs.h>
/* Read from kernel buffer at src to user/kernel buffer defined
* by the uio structure. Advance the pointer in the uio struct
* as we go.
*/
int
xfs_uio_read(caddr_t src, size_t len, struct uio *uio)
{
size_t count;
if (!len || !uio->uio_resid)
return 0;
count = uio->uio_iov->iov_len;
if (!count)
return 0;
if (count > len)
count = len;
if (uio->uio_segflg == UIO_USERSPACE) {
if (copy_to_user(uio->uio_iov->iov_base, src, count))
return EFAULT;
} else {
ASSERT(uio->uio_segflg == UIO_SYSSPACE);
memcpy(uio->uio_iov->iov_base, src, count);
}
uio->uio_iov->iov_base = (void*)((char*)uio->uio_iov->iov_base + count);
uio->uio_iov->iov_len -= count;
uio->uio_offset += count;
uio->uio_resid -= count;
return 0;
}
/*
* Copyright (c) 2000-2003,2005 Silicon Graphics, Inc.
* All Rights Reserved.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it would be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
* Portions Copyright (c) 1982, 1986, 1993, 1994
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#ifndef __XFS_SUPPORT_MOVE_H__
#define __XFS_SUPPORT_MOVE_H__
#include <linux/uio.h>
#include <asm/uaccess.h>
/* Segment flag values. */
enum uio_seg {
UIO_USERSPACE, /* from user data space */
UIO_SYSSPACE, /* from system space */
};
struct uio {
struct kvec *uio_iov; /* pointer to array of iovecs */
int uio_iovcnt; /* number of iovecs in array */
xfs_off_t uio_offset; /* offset in file this uio corresponds to */
int uio_resid; /* residual i/o count */
enum uio_seg uio_segflg; /* see above */
};
typedef struct uio uio_t;
typedef struct kvec iovec_t;
extern int xfs_uio_read (caddr_t, size_t, uio_t *);
#endif /* __XFS_SUPPORT_MOVE_H__ */
......@@ -32,6 +32,7 @@
#include "xfs_btree.h"
#include "xfs_acl.h"
#include "xfs_attr.h"
#include "xfs_vnodeops.h"
#include <linux/capability.h>
#include <linux/posix_acl_xattr.h>
......@@ -241,7 +242,7 @@ xfs_acl_vget(
bhv_vattr_t va;
va.va_mask = XFS_AT_MODE;
error = bhv_vop_getattr(vp, &va, 0, sys_cred);
error = xfs_getattr(xfs_vtoi(vp), &va, 0);
if (error)
goto out;
xfs_acl_sync_mode(va.va_mode, xfs_acl);
......@@ -265,9 +266,10 @@ xfs_acl_vremove(
VN_HOLD(vp);
error = xfs_acl_allow_set(vp, kind);
if (!error) {
error = bhv_vop_attr_remove(vp, kind == _ACL_TYPE_DEFAULT?
error = xfs_attr_remove(xfs_vtoi(vp),
kind == _ACL_TYPE_DEFAULT?
SGI_ACL_DEFAULT: SGI_ACL_FILE,
ATTR_ROOT, sys_cred);
ATTR_ROOT);
if (error == ENOATTR)
error = 0; /* 'scool */
}
......@@ -370,17 +372,18 @@ xfs_acl_allow_set(
bhv_vnode_t *vp,
int kind)
{
xfs_inode_t *ip = xfs_vtoi(vp);
bhv_vattr_t va;
int error;
if (vp->v_inode.i_flags & (S_IMMUTABLE|S_APPEND))
if (vp->i_flags & (S_IMMUTABLE|S_APPEND))
return EPERM;
if (kind == _ACL_TYPE_DEFAULT && !VN_ISDIR(vp))
return ENOTDIR;
if (vp->v_vfsp->vfs_flag & VFS_RDONLY)
if (vp->i_sb->s_flags & MS_RDONLY)
return EROFS;
va.va_mask = XFS_AT_UID;
error = bhv_vop_getattr(vp, &va, 0, NULL);
error = xfs_getattr(ip, &va, 0);
if (error)
return error;
if (va.va_uid != current->fsuid && !capable(CAP_FOWNER))
......@@ -613,7 +616,8 @@ xfs_acl_get_attr(
ASSERT((flags & ATTR_KERNOVAL) ? (aclp == NULL) : 1);
flags |= ATTR_ROOT;
*error = bhv_vop_attr_get(vp, kind == _ACL_TYPE_ACCESS ?
*error = xfs_attr_get(xfs_vtoi(vp),
kind == _ACL_TYPE_ACCESS ?
SGI_ACL_FILE : SGI_ACL_DEFAULT,
(char *)aclp, &len, flags, sys_cred);
if (*error || (flags & ATTR_KERNOVAL))
......@@ -651,9 +655,10 @@ xfs_acl_set_attr(
INT_SET(newace->ae_perm, ARCH_CONVERT, ace->ae_perm);
}
INT_SET(newacl->acl_cnt, ARCH_CONVERT, aclp->acl_cnt);
*error = bhv_vop_attr_set(vp, kind == _ACL_TYPE_ACCESS ?
*error = xfs_attr_set(xfs_vtoi(vp),
kind == _ACL_TYPE_ACCESS ?
SGI_ACL_FILE: SGI_ACL_DEFAULT,
(char *)newacl, len, ATTR_ROOT, sys_cred);
(char *)newacl, len, ATTR_ROOT);
_ACL_FREE(newacl);
}
......@@ -675,7 +680,7 @@ xfs_acl_vtoacl(
if (!error) {
/* Got the ACL, need the mode... */
va.va_mask = XFS_AT_MODE;
error = bhv_vop_getattr(vp, &va, 0, sys_cred);
error = xfs_getattr(xfs_vtoi(vp), &va, 0);
}
if (error)
......@@ -699,7 +704,7 @@ xfs_acl_vtoacl(
int
xfs_acl_inherit(
bhv_vnode_t *vp,
bhv_vattr_t *vap,
mode_t mode,
xfs_acl_t *pdaclp)
{
xfs_acl_t *cacl;
......@@ -727,7 +732,7 @@ xfs_acl_inherit(
return ENOMEM;
memcpy(cacl, pdaclp, sizeof(xfs_acl_t));
xfs_acl_filter_mode(vap->va_mode, cacl);
xfs_acl_filter_mode(mode, cacl);
xfs_acl_setmode(vp, cacl, &basicperms);
/*
......@@ -773,7 +778,7 @@ xfs_acl_setmode(
* mode. The m:: bits take precedence over the g:: bits.
*/
va.va_mask = XFS_AT_MODE;
error = bhv_vop_getattr(vp, &va, 0, sys_cred);
error = xfs_getattr(xfs_vtoi(vp), &va, 0);
if (error)
return error;
......@@ -807,7 +812,7 @@ xfs_acl_setmode(
if (gap && nomask)
va.va_mode |= gap->ae_perm << 3;
return bhv_vop_setattr(vp, &va, 0, sys_cred);
return xfs_setattr(xfs_vtoi(vp), &va, 0, sys_cred);
}
/*
......
......@@ -50,7 +50,6 @@ typedef struct xfs_acl {
#ifdef CONFIG_XFS_POSIX_ACL
struct vattr;
struct bhv_vnode;
struct xfs_inode;
extern struct kmem_zone *xfs_acl_zone;
......@@ -58,20 +57,20 @@ extern struct kmem_zone *xfs_acl_zone;
(zone) = kmem_zone_init(sizeof(xfs_acl_t), (name))
#define xfs_acl_zone_destroy(zone) kmem_zone_destroy(zone)
extern int xfs_acl_inherit(struct bhv_vnode *, struct bhv_vattr *, xfs_acl_t *);
extern int xfs_acl_inherit(bhv_vnode_t *, mode_t mode, xfs_acl_t *);
extern int xfs_acl_iaccess(struct xfs_inode *, mode_t, cred_t *);
extern int xfs_acl_vtoacl(struct bhv_vnode *, xfs_acl_t *, xfs_acl_t *);
extern int xfs_acl_vhasacl_access(struct bhv_vnode *);
extern int xfs_acl_vhasacl_default(struct bhv_vnode *);
extern int xfs_acl_vset(struct bhv_vnode *, void *, size_t, int);
extern int xfs_acl_vget(struct bhv_vnode *, void *, size_t, int);
extern int xfs_acl_vremove(struct bhv_vnode *, int);
extern int xfs_acl_vtoacl(bhv_vnode_t *, xfs_acl_t *, xfs_acl_t *);
extern int xfs_acl_vhasacl_access(bhv_vnode_t *);
extern int xfs_acl_vhasacl_default(bhv_vnode_t *);
extern int xfs_acl_vset(bhv_vnode_t *, void *, size_t, int);
extern int xfs_acl_vget(bhv_vnode_t *, void *, size_t, int);
extern int xfs_acl_vremove(bhv_vnode_t *, int);
#define _ACL_TYPE_ACCESS 1
#define _ACL_TYPE_DEFAULT 2
#define _ACL_PERM_INVALID(perm) ((perm) & ~(ACL_READ|ACL_WRITE|ACL_EXECUTE))
#define _ACL_INHERIT(c,v,d) (xfs_acl_inherit(c,v,d))
#define _ACL_INHERIT(c,m,d) (xfs_acl_inherit(c,m,d))
#define _ACL_GET_ACCESS(pv,pa) (xfs_acl_vtoacl(pv,pa,NULL) == 0)
#define _ACL_GET_DEFAULT(pv,pd) (xfs_acl_vtoacl(pv,NULL,pd) == 0)
#define _ACL_ACCESS_EXISTS xfs_acl_vhasacl_access
......@@ -91,7 +90,7 @@ extern int xfs_acl_vremove(struct bhv_vnode *, int);
#define xfs_acl_vhasacl_default(v) (0)
#define _ACL_ALLOC(a) (1) /* successfully allocate nothing */
#define _ACL_FREE(a) ((void)0)
#define _ACL_INHERIT(c,v,d) (0)
#define _ACL_INHERIT(c,m,d) (0)
#define _ACL_GET_ACCESS(pv,pa) (0)
#define _ACL_GET_DEFAULT(pv,pd) (0)
#define _ACL_ACCESS_EXISTS (NULL)
......
......@@ -197,6 +197,10 @@ typedef struct xfs_perag
#endif
xfs_perag_busy_t *pagb_list; /* unstable blocks */
atomic_t pagf_fstrms; /* # of filestreams active in this AG */
int pag_ici_init; /* incore inode cache initialised */
rwlock_t pag_ici_lock; /* incore inode lock */
struct radix_tree_root pag_ici_root; /* incore inode cache root */
} xfs_perag_t;
#define XFS_AG_MAXLEVELS(mp) ((mp)->m_ag_maxlevels)
......
......@@ -49,6 +49,7 @@
#include "xfs_trans_space.h"
#include "xfs_acl.h"
#include "xfs_rw.h"
#include "xfs_vnodeops.h"
/*
* xfs_attr.c
......@@ -156,10 +157,14 @@ xfs_attr_fetch(xfs_inode_t *ip, const char *name, int namelen,
}
int
xfs_attr_get(bhv_desc_t *bdp, const char *name, char *value, int *valuelenp,
int flags, struct cred *cred)
xfs_attr_get(
xfs_inode_t *ip,
const char *name,
char *value,
int *valuelenp,
int flags,
cred_t *cred)
{
xfs_inode_t *ip = XFS_BHVTOI(bdp);
int error, namelen;
XFS_STATS_INC(xs_attr_get);
......@@ -417,10 +422,13 @@ xfs_attr_set_int(xfs_inode_t *dp, const char *name, int namelen,
}
int
xfs_attr_set(bhv_desc_t *bdp, const char *name, char *value, int valuelen, int flags,
struct cred *cred)
xfs_attr_set(
xfs_inode_t *dp,
const char *name,
char *value,
int valuelen,
int flags)
{
xfs_inode_t *dp;
int namelen;
namelen = strlen(name);
......@@ -429,7 +437,6 @@ xfs_attr_set(bhv_desc_t *bdp, const char *name, char *value, int valuelen, int f
XFS_STATS_INC(xs_attr_set);
dp = XFS_BHVTOI(bdp);
if (XFS_FORCED_SHUTDOWN(dp->i_mount))
return (EIO);
......@@ -563,10 +570,12 @@ xfs_attr_remove_int(xfs_inode_t *dp, const char *name, int namelen, int flags)
}
int
xfs_attr_remove(bhv_desc_t *bdp, const char *name, int flags, struct cred *cred)
xfs_attr_remove(
xfs_inode_t *dp,
const char *name,
int flags)
{
xfs_inode_t *dp;
int namelen;
int namelen;
namelen = strlen(name);
if (namelen >= MAXNAMELEN)
......@@ -574,7 +583,6 @@ xfs_attr_remove(bhv_desc_t *bdp, const char *name, int flags, struct cred *cred)
XFS_STATS_INC(xs_attr_remove);
dp = XFS_BHVTOI(bdp);
if (XFS_FORCED_SHUTDOWN(dp->i_mount))
return (EIO);
......@@ -702,11 +710,14 @@ xfs_attr_kern_list_sizes(xfs_attr_list_context_t *context, attrnames_t *namesp,
* success.
*/
int
xfs_attr_list(bhv_desc_t *bdp, char *buffer, int bufsize, int flags,
attrlist_cursor_kern_t *cursor, struct cred *cred)
xfs_attr_list(
xfs_inode_t *dp,
char *buffer,
int bufsize,
int flags,
attrlist_cursor_kern_t *cursor)
{
xfs_attr_list_context_t context;
xfs_inode_t *dp;
int error;
XFS_STATS_INC(xs_attr_list);
......@@ -731,7 +742,7 @@ xfs_attr_list(bhv_desc_t *bdp, char *buffer, int bufsize, int flags,
/*
* Initialize the output buffer.
*/
context.dp = dp = XFS_BHVTOI(bdp);
context.dp = dp;
context.cursor = cursor;
context.count = 0;
context.dupcnt = 0;
......@@ -2502,7 +2513,7 @@ STATIC int
attr_generic_set(
bhv_vnode_t *vp, char *name, void *data, size_t size, int xflags)
{
return -bhv_vop_attr_set(vp, name, data, size, xflags, NULL);
return -xfs_attr_set(xfs_vtoi(vp), name, data, size, xflags);
}
STATIC int
......@@ -2511,7 +2522,8 @@ attr_generic_get(
{
int error, asize = size;
error = bhv_vop_attr_get(vp, name, data, &asize, xflags, NULL);
error = xfs_attr_get(xfs_vtoi(vp), name, data,
&asize, xflags, NULL);
if (!error)
return asize;
return -error;
......@@ -2521,7 +2533,7 @@ STATIC int
attr_generic_remove(
bhv_vnode_t *vp, char *name, int xflags)
{
return -bhv_vop_attr_remove(vp, name, xflags, NULL);
return -xfs_attr_remove(xfs_vtoi(vp), name, xflags);
}
STATIC int
......@@ -2576,7 +2588,7 @@ attr_generic_list(
attrlist_cursor_kern_t cursor = { 0 };
int error;
error = bhv_vop_attr_list(vp, data, size, xflags, &cursor, NULL);
error = xfs_attr_list(xfs_vtoi(vp), data, size, xflags, &cursor);
if (error > 0)
return -error;
*result = -error;
......
......@@ -36,14 +36,13 @@
*========================================================================*/
struct cred;
struct bhv_vnode;
struct xfs_attr_list_context;
typedef int (*attrset_t)(struct bhv_vnode *, char *, void *, size_t, int);
typedef int (*attrget_t)(struct bhv_vnode *, char *, void *, size_t, int);
typedef int (*attrremove_t)(struct bhv_vnode *, char *, int);
typedef int (*attrexists_t)(struct bhv_vnode *);
typedef int (*attrcapable_t)(struct bhv_vnode *, struct cred *);
typedef int (*attrset_t)(bhv_vnode_t *, char *, void *, size_t, int);
typedef int (*attrget_t)(bhv_vnode_t *, char *, void *, size_t, int);
typedef int (*attrremove_t)(bhv_vnode_t *, char *, int);
typedef int (*attrexists_t)(bhv_vnode_t *);
typedef int (*attrcapable_t)(bhv_vnode_t *, struct cred *);
typedef struct attrnames {
char * attr_name;
......@@ -64,7 +63,7 @@ extern struct attrnames attr_trusted;
extern struct attrnames *attr_namespaces[ATTR_NAMECOUNT];
extern attrnames_t *attr_lookup_namespace(char *, attrnames_t **, int);
extern int attr_generic_list(struct bhv_vnode *, void *, size_t, int, ssize_t *);
extern int attr_generic_list(bhv_vnode_t *, void *, size_t, int, ssize_t *);
#define ATTR_DONTFOLLOW 0x0001 /* -- unused, from IRIX -- */
#define ATTR_ROOT 0x0002 /* use attrs in root (trusted) namespace */
......@@ -159,12 +158,8 @@ struct xfs_da_args;
/*
* Overall external interface routines.
*/
int xfs_attr_get(bhv_desc_t *, const char *, char *, int *, int, struct cred *);
int xfs_attr_set(bhv_desc_t *, const char *, char *, int, int, struct cred *);
int xfs_attr_set_int(struct xfs_inode *, const char *, int, char *, int, int);
int xfs_attr_remove(bhv_desc_t *, const char *, int, struct cred *);
int xfs_attr_remove_int(struct xfs_inode *, const char *, int, int);
int xfs_attr_list(bhv_desc_t *, char *, int, int, struct attrlist_cursor_kern *, struct cred *);
int xfs_attr_list_int(struct xfs_attr_list_context *);
int xfs_attr_inactive(struct xfs_inode *dp);
......
/*
* Copyright (c) 2000-2003,2005 Silicon Graphics, Inc.
* All Rights Reserved.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it would be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "xfs.h"
/*
* Source file used to associate/disassociate behaviors with virtualized
* objects. See xfs_behavior.h for more information about behaviors, etc.
*
* The implementation is split between functions in this file and macros
* in xfs_behavior.h.
*/
/*
* Insert a new behavior descriptor into a behavior chain.
*
* The behavior chain is ordered based on the 'position' number which
* lives in the first field of the ops vector (higher numbers first).
*
* Attempts to insert duplicate ops result in an EINVAL return code.
* Otherwise, return 0 to indicate success.
*/
int
bhv_insert(bhv_head_t *bhp, bhv_desc_t *bdp)
{
bhv_desc_t *curdesc, *prev;
int position;
/*
* Validate the position value of the new behavior.
*/
position = BHV_POSITION(bdp);
ASSERT(position >= BHV_POSITION_BASE && position <= BHV_POSITION_TOP);
/*
* Find location to insert behavior. Check for duplicates.
*/
prev = NULL;
for (curdesc = bhp->bh_first;
curdesc != NULL;
curdesc = curdesc->bd_next) {
/* Check for duplication. */
if (curdesc->bd_ops == bdp->bd_ops) {
ASSERT(0);
return EINVAL;
}
/* Find correct position */
if (position >= BHV_POSITION(curdesc)) {
ASSERT(position != BHV_POSITION(curdesc));
break; /* found it */
}
prev = curdesc;
}
if (prev == NULL) {
/* insert at front of chain */
bdp->bd_next = bhp->bh_first;
bhp->bh_first = bdp;
} else {
/* insert after prev */
bdp->bd_next = prev->bd_next;
prev->bd_next = bdp;
}
return 0;
}
/*
* Remove a behavior descriptor from a position in a behavior chain;
* the position is guaranteed not to be the first position.
* Should only be called by the bhv_remove() macro.
*/
void
bhv_remove_not_first(bhv_head_t *bhp, bhv_desc_t *bdp)
{
bhv_desc_t *curdesc, *prev;
ASSERT(bhp->bh_first != NULL);
ASSERT(bhp->bh_first->bd_next != NULL);
prev = bhp->bh_first;
for (curdesc = bhp->bh_first->bd_next;
curdesc != NULL;
curdesc = curdesc->bd_next) {
if (curdesc == bdp)
break; /* found it */
prev = curdesc;
}
ASSERT(curdesc == bdp);
prev->bd_next = bdp->bd_next; /* remove from after prev */
}
/*
* Looks for the first behavior within a specified range of positions.
* Return the associated behavior descriptor. Or NULL, if none found.
*/
bhv_desc_t *
bhv_lookup_range(bhv_head_t *bhp, int low, int high)
{
bhv_desc_t *curdesc;
for (curdesc = bhp->bh_first;
curdesc != NULL;
curdesc = curdesc->bd_next) {
int position = BHV_POSITION(curdesc);
if (position <= high) {
if (position >= low)
return curdesc;
return NULL;
}
}
return NULL;
}
/*
* Return the base behavior in the chain, or NULL if the chain
* is empty.
*
* The caller has not read locked the behavior chain, so acquire the
* lock before traversing the chain.
*/
bhv_desc_t *
bhv_base(bhv_head_t *bhp)
{
bhv_desc_t *curdesc;
for (curdesc = bhp->bh_first;
curdesc != NULL;
curdesc = curdesc->bd_next) {
if (curdesc->bd_next == NULL) {
return curdesc;
}
}
return NULL;
}
void
bhv_head_init(
bhv_head_t *bhp,
char *name)
{
bhp->bh_first = NULL;
}
void
bhv_insert_initial(
bhv_head_t *bhp,
bhv_desc_t *bdp)
{
ASSERT(bhp->bh_first == NULL);
(bhp)->bh_first = bdp;
}
void
bhv_head_destroy(
bhv_head_t *bhp)
{
ASSERT(bhp->bh_first == NULL);
}
/*
* Copyright (c) 2000-2003,2005 Silicon Graphics, Inc.
* All Rights Reserved.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it would be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __XFS_BEHAVIOR_H__
#define __XFS_BEHAVIOR_H__
/*
* Header file used to associate behaviors with virtualized objects.
*
* A virtualized object is an internal, virtualized representation of
* OS entities such as persistent files, processes, or sockets. Examples
* of virtualized objects include vnodes, vprocs, and vsockets. Often
* a virtualized object is referred to simply as an "object."
*
* A behavior is essentially an implementation layer associated with
* an object. Multiple behaviors for an object are chained together,
* the order of chaining determining the order of invocation. Each
* behavior of a given object implements the same set of interfaces
* (e.g., the VOP interfaces).
*
* Behaviors may be dynamically inserted into an object's behavior chain,
* such that the addition is transparent to consumers that already have
* references to the object. Typically, a given behavior will be inserted
* at a particular location in the behavior chain. Insertion of new
* behaviors is synchronized with operations-in-progress (oip's) so that
* the oip's always see a consistent view of the chain.
*
* The term "interposition" is used to refer to the act of inserting
* a behavior such that it interposes on (i.e., is inserted in front
* of) a particular other behavior. A key example of this is when a
* system implementing distributed single system image wishes to
* interpose a distribution layer (providing distributed coherency)
* in front of an object that is otherwise only accessed locally.
*
* Note that the traditional vnode/inode combination is simply a virtualized
* object that has exactly one associated behavior.
*
* Behavior synchronization is logic which is necessary under certain
* circumstances that there is no conflict between ongoing operations
* traversing the behavior chain and those dynamically modifying the
* behavior chain. Because behavior synchronization adds extra overhead
* to virtual operation invocation, we want to restrict, as much as
* we can, the requirement for this extra code, to those situations
* in which it is truly necessary.
*
* Behavior synchronization is needed whenever there's at least one class
* of object in the system for which:
* 1) multiple behaviors for a given object are supported,
* -- AND --
* 2a) insertion of a new behavior can happen dynamically at any time during
* the life of an active object,
* -- AND --
* 3a) insertion of a new behavior needs to synchronize with existing
* ops-in-progress.
* -- OR --
* 3b) multiple different behaviors can be dynamically inserted at
* any time during the life of an active object
* -- OR --
* 3c) removal of a behavior can occur at any time during the life of
* an active object.
* -- OR --
* 2b) removal of a behavior can occur at any time during the life of an
* active object
*
*/
/*
* Behavior head. Head of the chain of behaviors.
* Contained within each virtualized object data structure.
*/
typedef struct bhv_head {
struct bhv_desc *bh_first; /* first behavior in chain */
} bhv_head_t;
/*
* Behavior descriptor. Descriptor associated with each behavior.
* Contained within the behavior's private data structure.
*/
typedef struct bhv_desc {
void *bd_pdata; /* private data for this behavior */
void *bd_vobj; /* virtual object associated with */
void *bd_ops; /* ops for this behavior */
struct bhv_desc *bd_next; /* next behavior in chain */
} bhv_desc_t;
/*
* Behavior identity field. A behavior's identity determines the position
* where it lives within a behavior chain, and it's always the first field
* of the behavior's ops vector. The optional id field further identifies the
* subsystem responsible for the behavior.
*/
typedef struct bhv_identity {
__u16 bi_id; /* owning subsystem id */
__u16 bi_position; /* position in chain */
} bhv_identity_t;
typedef bhv_identity_t bhv_position_t;
#define BHV_IDENTITY_INIT(id,pos) {id, pos}
#define BHV_IDENTITY_INIT_POSITION(pos) BHV_IDENTITY_INIT(0, pos)
/*
* Define boundaries of position values.
*/
#define BHV_POSITION_INVALID 0 /* invalid position number */
#define BHV_POSITION_BASE 1 /* base (last) implementation layer */
#define BHV_POSITION_TOP 63 /* top (first) implementation layer */
/*
* Plumbing macros.
*/
#define BHV_HEAD_FIRST(bhp) (ASSERT((bhp)->bh_first), (bhp)->bh_first)
#define BHV_NEXT(bdp) (ASSERT((bdp)->bd_next), (bdp)->bd_next)
#define BHV_NEXTNULL(bdp) ((bdp)->bd_next)
#define BHV_VOBJ(bdp) (ASSERT((bdp)->bd_vobj), (bdp)->bd_vobj)
#define BHV_VOBJNULL(bdp) ((bdp)->bd_vobj)
#define BHV_PDATA(bdp) (bdp)->bd_pdata
#define BHV_OPS(bdp) (bdp)->bd_ops
#define BHV_IDENTITY(bdp) ((bhv_identity_t *)(bdp)->bd_ops)
#define BHV_POSITION(bdp) (BHV_IDENTITY(bdp)->bi_position)
extern void bhv_head_init(bhv_head_t *, char *);
extern void bhv_head_destroy(bhv_head_t *);
extern int bhv_insert(bhv_head_t *, bhv_desc_t *);
extern void bhv_insert_initial(bhv_head_t *, bhv_desc_t *);
/*
* Initialize a new behavior descriptor.
* Arguments:
* bdp - pointer to behavior descriptor
* pdata - pointer to behavior's private data
* vobj - pointer to associated virtual object
* ops - pointer to ops for this behavior
*/
#define bhv_desc_init(bdp, pdata, vobj, ops) \
{ \
(bdp)->bd_pdata = pdata; \
(bdp)->bd_vobj = vobj; \
(bdp)->bd_ops = ops; \
(bdp)->bd_next = NULL; \
}
/*
* Remove a behavior descriptor from a behavior chain.
*/
#define bhv_remove(bhp, bdp) \
{ \
if ((bhp)->bh_first == (bdp)) { \
/* \
* Remove from front of chain. \
* Atomic wrt oip's. \
*/ \
(bhp)->bh_first = (bdp)->bd_next; \
} else { \
/* remove from non-front of chain */ \
bhv_remove_not_first(bhp, bdp); \
} \
(bdp)->bd_vobj = NULL; \
}
/*
* Behavior module prototypes.
*/
extern void bhv_remove_not_first(bhv_head_t *bhp, bhv_desc_t *bdp);
extern bhv_desc_t * bhv_lookup_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_base_unlocked bhv_base
#endif /* __XFS_BEHAVIOR_H__ */
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.
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