提交 347c53dc 编写于 作者: L 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
  ...
......@@ -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__ */
......@@ -47,6 +47,7 @@
#include "xfs_utils.h"
#include "xfs_dfrag.h"
#include "xfs_fsops.h"
#include "xfs_vnodeops.h"
#include <linux/capability.h>
#include <linux/dcache.h>
......@@ -137,7 +138,8 @@ xfs_find_handle(
vp = vn_from_inode(inode);
/* now we can grab the fsid */
memcpy(&handle.ha_fsid, vp->v_vfsp->vfs_altfsid, sizeof(xfs_fsid_t));
memcpy(&handle.ha_fsid, XFS_I(inode)->i_mount->m_fixedfsid,
sizeof(xfs_fsid_t));
hsize = sizeof(xfs_fsid_t);
if (cmd != XFS_IOC_PATH_TO_FSHANDLE) {
......@@ -349,19 +351,44 @@ xfs_open_by_handle(
return new_fd;
}
/*
* This is a copy from fs/namei.c:vfs_readlink(), except for removing it's
* unused first argument.
*/
STATIC int
do_readlink(
char __user *buffer,
int buflen,
const char *link)
{
int len;
len = PTR_ERR(link);
if (IS_ERR(link))
goto out;
len = strlen(link);
if (len > (unsigned) buflen)
len = buflen;
if (copy_to_user(buffer, link, len))
len = -EFAULT;
out:
return len;
}
STATIC int
xfs_readlink_by_handle(
xfs_mount_t *mp,
void __user *arg,
struct inode *parinode)
{
int error;
struct iovec aiov;
struct uio auio;
struct inode *inode;
xfs_fsop_handlereq_t hreq;
bhv_vnode_t *vp;
__u32 olen;
void *link;
int error;
if (!capable(CAP_SYS_ADMIN))
return -XFS_ERROR(EPERM);
......@@ -374,29 +401,31 @@ xfs_readlink_by_handle(
/* Restrict this handle operation to symlinks only. */
if (!S_ISLNK(inode->i_mode)) {
VN_RELE(vp);
return -XFS_ERROR(EINVAL);
error = -XFS_ERROR(EINVAL);
goto out_iput;
}
if (copy_from_user(&olen, hreq.ohandlen, sizeof(__u32))) {
VN_RELE(vp);
return -XFS_ERROR(EFAULT);
error = -XFS_ERROR(EFAULT);
goto out_iput;
}
aiov.iov_len = olen;
aiov.iov_base = hreq.ohandle;
auio.uio_iov = (struct kvec *)&aiov;
auio.uio_iovcnt = 1;
auio.uio_offset = 0;
auio.uio_segflg = UIO_USERSPACE;
auio.uio_resid = olen;
link = kmalloc(MAXPATHLEN+1, GFP_KERNEL);
if (!link)
goto out_iput;
error = bhv_vop_readlink(vp, &auio, IO_INVIS, NULL);
VN_RELE(vp);
error = -xfs_readlink(XFS_I(inode), link);
if (error)
return -error;
goto out_kfree;
error = do_readlink(hreq.ohandle, olen, link);
if (error)
goto out_kfree;
return (olen - auio.uio_resid);
out_kfree:
kfree(link);
out_iput:
iput(inode);
return error;
}
STATIC int
......@@ -409,7 +438,6 @@ xfs_fssetdm_by_handle(
struct fsdmidata fsd;
xfs_fsop_setdm_handlereq_t dmhreq;
struct inode *inode;
bhv_desc_t *bdp;
bhv_vnode_t *vp;
if (!capable(CAP_MKNOD))
......@@ -431,8 +459,8 @@ xfs_fssetdm_by_handle(
return -XFS_ERROR(EFAULT);
}
bdp = bhv_base_unlocked(VN_BHV_HEAD(vp));
error = xfs_set_dmattrs(bdp, fsd.fsd_dmevmask, fsd.fsd_dmstate, NULL);
error = xfs_set_dmattrs(xfs_vtoi(vp),
fsd.fsd_dmevmask, fsd.fsd_dmstate);
VN_RELE(vp);
if (error)
......@@ -470,8 +498,8 @@ xfs_attrlist_by_handle(
goto out_vn_rele;
cursor = (attrlist_cursor_kern_t *)&al_hreq.pos;
error = bhv_vop_attr_list(vp, kbuf, al_hreq.buflen, al_hreq.flags,
cursor, NULL);
error = xfs_attr_list(XFS_I(inode), kbuf, al_hreq.buflen,
al_hreq.flags, cursor);
if (error)
goto out_kfree;
......@@ -488,7 +516,7 @@ xfs_attrlist_by_handle(
STATIC int
xfs_attrmulti_attr_get(
bhv_vnode_t *vp,
struct inode *inode,
char *name,
char __user *ubuf,
__uint32_t *len,
......@@ -503,7 +531,7 @@ xfs_attrmulti_attr_get(
if (!kbuf)
return ENOMEM;
error = bhv_vop_attr_get(vp, name, kbuf, len, flags, NULL);
error = xfs_attr_get(XFS_I(inode), name, kbuf, len, flags, NULL);
if (error)
goto out_kfree;
......@@ -517,7 +545,7 @@ xfs_attrmulti_attr_get(
STATIC int
xfs_attrmulti_attr_set(
bhv_vnode_t *vp,
struct inode *inode,
char *name,
const char __user *ubuf,
__uint32_t len,
......@@ -526,9 +554,9 @@ xfs_attrmulti_attr_set(
char *kbuf;
int error = EFAULT;
if (IS_RDONLY(&vp->v_inode))
if (IS_RDONLY(inode))
return -EROFS;
if (IS_IMMUTABLE(&vp->v_inode) || IS_APPEND(&vp->v_inode))
if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
return EPERM;
if (len > XATTR_SIZE_MAX)
return EINVAL;
......@@ -540,7 +568,7 @@ xfs_attrmulti_attr_set(
if (copy_from_user(kbuf, ubuf, len))
goto out_kfree;
error = bhv_vop_attr_set(vp, name, kbuf, len, flags, NULL);
error = xfs_attr_set(XFS_I(inode), name, kbuf, len, flags);
out_kfree:
kfree(kbuf);
......@@ -549,15 +577,15 @@ xfs_attrmulti_attr_set(
STATIC int
xfs_attrmulti_attr_remove(
bhv_vnode_t *vp,
struct inode *inode,
char *name,
__uint32_t flags)
{
if (IS_RDONLY(&vp->v_inode))
if (IS_RDONLY(inode))
return -EROFS;
if (IS_IMMUTABLE(&vp->v_inode) || IS_APPEND(&vp->v_inode))
if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
return EPERM;
return bhv_vop_attr_remove(vp, name, flags, NULL);
return xfs_attr_remove(XFS_I(inode), name, flags);
}
STATIC int
......@@ -613,17 +641,17 @@ xfs_attrmulti_by_handle(
switch (ops[i].am_opcode) {
case ATTR_OP_GET:
ops[i].am_error = xfs_attrmulti_attr_get(vp,
ops[i].am_error = xfs_attrmulti_attr_get(inode,
attr_name, ops[i].am_attrvalue,
&ops[i].am_length, ops[i].am_flags);
break;
case ATTR_OP_SET:
ops[i].am_error = xfs_attrmulti_attr_set(vp,
ops[i].am_error = xfs_attrmulti_attr_set(inode,
attr_name, ops[i].am_attrvalue,
ops[i].am_length, ops[i].am_flags);
break;
case ATTR_OP_REMOVE:
ops[i].am_error = xfs_attrmulti_attr_remove(vp,
ops[i].am_error = xfs_attrmulti_attr_remove(inode,
attr_name, ops[i].am_flags);
break;
default:
......@@ -649,7 +677,7 @@ xfs_attrmulti_by_handle(
STATIC int
xfs_ioc_space(
bhv_desc_t *bdp,
struct xfs_inode *ip,
struct inode *inode,
struct file *filp,
int flags,
......@@ -680,38 +708,38 @@ xfs_ioc_xattr(
unsigned int cmd,
void __user *arg);
STATIC int
xfs_ioc_fsgetxattr(
xfs_inode_t *ip,
int attr,
void __user *arg);
STATIC int
xfs_ioc_getbmap(
bhv_desc_t *bdp,
struct xfs_inode *ip,
int flags,
unsigned int cmd,
void __user *arg);
STATIC int
xfs_ioc_getbmapx(
bhv_desc_t *bdp,
struct xfs_inode *ip,
void __user *arg);
int
xfs_ioctl(
bhv_desc_t *bdp,
struct inode *inode,
xfs_inode_t *ip,
struct file *filp,
int ioflags,
unsigned int cmd,
void __user *arg)
{
struct inode *inode = filp->f_path.dentry->d_inode;
bhv_vnode_t *vp = vn_from_inode(inode);
xfs_mount_t *mp = ip->i_mount;
int error;
bhv_vnode_t *vp;
xfs_inode_t *ip;
xfs_mount_t *mp;
vp = vn_from_inode(inode);
vn_trace_entry(vp, "xfs_ioctl", (inst_t *)__return_address);
ip = XFS_BHVTOI(bdp);
mp = ip->i_mount;
vn_trace_entry(XFS_I(inode), "xfs_ioctl", (inst_t *)__return_address);
switch (cmd) {
......@@ -731,7 +759,7 @@ xfs_ioctl(
!capable(CAP_SYS_ADMIN))
return -EPERM;
return xfs_ioc_space(bdp, inode, filp, ioflags, cmd, arg);
return xfs_ioc_space(ip, inode, filp, ioflags, cmd, arg);
case XFS_IOC_DIOINFO: {
struct dioattr da;
......@@ -761,11 +789,13 @@ xfs_ioctl(
case XFS_IOC_GETVERSION:
return put_user(inode->i_generation, (int __user *)arg);
case XFS_IOC_FSGETXATTR:
return xfs_ioc_fsgetxattr(ip, 0, arg);
case XFS_IOC_FSGETXATTRA:
return xfs_ioc_fsgetxattr(ip, 1, arg);
case XFS_IOC_GETXFLAGS:
case XFS_IOC_SETXFLAGS:
case XFS_IOC_FSGETXATTR:
case XFS_IOC_FSSETXATTR:
case XFS_IOC_FSGETXATTRA:
return xfs_ioc_xattr(vp, ip, filp, cmd, arg);
case XFS_IOC_FSSETDM: {
......@@ -774,17 +804,17 @@ xfs_ioctl(
if (copy_from_user(&dmi, arg, sizeof(dmi)))
return -XFS_ERROR(EFAULT);
error = xfs_set_dmattrs(bdp, dmi.fsd_dmevmask, dmi.fsd_dmstate,
NULL);
error = xfs_set_dmattrs(ip, dmi.fsd_dmevmask,
dmi.fsd_dmstate);
return -error;
}
case XFS_IOC_GETBMAP:
case XFS_IOC_GETBMAPA:
return xfs_ioc_getbmap(bdp, ioflags, cmd, arg);
return xfs_ioc_getbmap(ip, ioflags, cmd, arg);
case XFS_IOC_GETBMAPX:
return xfs_ioc_getbmapx(bdp, arg);
return xfs_ioc_getbmapx(ip, arg);
case XFS_IOC_FD_TO_HANDLE:
case XFS_IOC_PATH_TO_HANDLE:
......@@ -944,7 +974,7 @@ xfs_ioctl(
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
error = xfs_errortag_clearall(mp);
error = xfs_errortag_clearall(mp, 1);
return -error;
default:
......@@ -954,7 +984,7 @@ xfs_ioctl(
STATIC int
xfs_ioc_space(
bhv_desc_t *bdp,
struct xfs_inode *ip,
struct inode *inode,
struct file *filp,
int ioflags,
......@@ -982,7 +1012,7 @@ xfs_ioc_space(
if (ioflags & IO_INVIS)
attr_flags |= ATTR_DMI;
error = xfs_change_file_space(bdp, cmd, &bf, filp->f_pos,
error = xfs_change_file_space(ip, cmd, &bf, filp->f_pos,
NULL, attr_flags);
return -error;
}
......@@ -1139,6 +1169,42 @@ xfs_di2lxflags(
return flags;
}
STATIC int
xfs_ioc_fsgetxattr(
xfs_inode_t *ip,
int attr,
void __user *arg)
{
struct fsxattr fa;
xfs_ilock(ip, XFS_ILOCK_SHARED);
fa.fsx_xflags = xfs_ip2xflags(ip);
fa.fsx_extsize = ip->i_d.di_extsize << ip->i_mount->m_sb.sb_blocklog;
fa.fsx_projid = ip->i_d.di_projid;
if (attr) {
if (ip->i_afp) {
if (ip->i_afp->if_flags & XFS_IFEXTENTS)
fa.fsx_nextents = ip->i_afp->if_bytes /
sizeof(xfs_bmbt_rec_t);
else
fa.fsx_nextents = ip->i_d.di_anextents;
} else
fa.fsx_nextents = 0;
} else {
if (ip->i_df.if_flags & XFS_IFEXTENTS)
fa.fsx_nextents = ip->i_df.if_bytes /
sizeof(xfs_bmbt_rec_t);
else
fa.fsx_nextents = ip->i_d.di_nextents;
}
xfs_iunlock(ip, XFS_ILOCK_SHARED);
if (copy_to_user(arg, &fa, sizeof(fa)))
return -EFAULT;
return 0;
}
STATIC int
xfs_ioc_xattr(
bhv_vnode_t *vp,
......@@ -1158,27 +1224,6 @@ xfs_ioc_xattr(
return -ENOMEM;
switch (cmd) {
case XFS_IOC_FSGETXATTR: {
vattr->va_mask = XFS_AT_XFLAGS | XFS_AT_EXTSIZE | \
XFS_AT_NEXTENTS | XFS_AT_PROJID;
error = bhv_vop_getattr(vp, vattr, 0, NULL);
if (unlikely(error)) {
error = -error;
break;
}
fa.fsx_xflags = vattr->va_xflags;
fa.fsx_extsize = vattr->va_extsize;
fa.fsx_nextents = vattr->va_nextents;
fa.fsx_projid = vattr->va_projid;
if (copy_to_user(arg, &fa, sizeof(fa))) {
error = -EFAULT;
break;
}
break;
}
case XFS_IOC_FSSETXATTR: {
if (copy_from_user(&fa, arg, sizeof(fa))) {
error = -EFAULT;
......@@ -1194,34 +1239,13 @@ xfs_ioc_xattr(
vattr->va_extsize = fa.fsx_extsize;
vattr->va_projid = fa.fsx_projid;
error = bhv_vop_setattr(vp, vattr, attr_flags, NULL);
error = xfs_setattr(ip, vattr, attr_flags, NULL);
if (likely(!error))
__vn_revalidate(vp, vattr); /* update flags */
error = -error;
break;
}
case XFS_IOC_FSGETXATTRA: {
vattr->va_mask = XFS_AT_XFLAGS | XFS_AT_EXTSIZE | \
XFS_AT_ANEXTENTS | XFS_AT_PROJID;
error = bhv_vop_getattr(vp, vattr, 0, NULL);
if (unlikely(error)) {
error = -error;
break;
}
fa.fsx_xflags = vattr->va_xflags;
fa.fsx_extsize = vattr->va_extsize;
fa.fsx_nextents = vattr->va_anextents;
fa.fsx_projid = vattr->va_projid;
if (copy_to_user(arg, &fa, sizeof(fa))) {
error = -EFAULT;
break;
}
break;
}
case XFS_IOC_GETXFLAGS: {
flags = xfs_di2lxflags(ip->i_d.di_flags);
if (copy_to_user(arg, &flags, sizeof(flags)))
......@@ -1250,7 +1274,7 @@ xfs_ioc_xattr(
vattr->va_xflags = xfs_merge_ioc_xflags(flags,
xfs_ip2xflags(ip));
error = bhv_vop_setattr(vp, vattr, attr_flags, NULL);
error = xfs_setattr(ip, vattr, attr_flags, NULL);
if (likely(!error))
__vn_revalidate(vp, vattr); /* update flags */
error = -error;
......@@ -1268,7 +1292,7 @@ xfs_ioc_xattr(
STATIC int
xfs_ioc_getbmap(
bhv_desc_t *bdp,
struct xfs_inode *ip,
int ioflags,
unsigned int cmd,
void __user *arg)
......@@ -1287,7 +1311,7 @@ xfs_ioc_getbmap(
if (ioflags & IO_INVIS)
iflags |= BMV_IF_NO_DMAPI_READ;
error = xfs_getbmap(bdp, &bm, (struct getbmap __user *)arg+1, iflags);
error = xfs_getbmap(ip, &bm, (struct getbmap __user *)arg+1, iflags);
if (error)
return -error;
......@@ -1298,7 +1322,7 @@ xfs_ioc_getbmap(
STATIC int
xfs_ioc_getbmapx(
bhv_desc_t *bdp,
struct xfs_inode *ip,
void __user *arg)
{
struct getbmapx bmx;
......@@ -1325,7 +1349,7 @@ xfs_ioc_getbmapx(
iflags |= BMV_IF_EXTENDED;
error = xfs_getbmap(bdp, &bm, (struct getbmapx __user *)arg+1, iflags);
error = xfs_getbmap(ip, &bm, (struct getbmapx __user *)arg+1, iflags);
if (error)
return -error;
......
......@@ -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;
}
......
......@@ -46,28 +46,13 @@
#include "xfs_attr.h"
#include "xfs_buf_item.h"
#include "xfs_utils.h"
#include "xfs_vnodeops.h"
#include <linux/capability.h>
#include <linux/xattr.h>
#include <linux/namei.h>
#include <linux/security.h>
/*
* Get a XFS inode from a given vnode.
*/
xfs_inode_t *
xfs_vtoi(
bhv_vnode_t *vp)
{
bhv_desc_t *bdp;
bdp = bhv_lookup_range(VN_BHV_HEAD(vp),
VNODE_POSITION_XFS, VNODE_POSITION_XFS);
if (unlikely(bdp == NULL))
return NULL;
return XFS_BHVTOI(bdp);
}
/*
* Bring the atime in the XFS inode uptodate.
* Used before logging the inode to disk or when the Linux inode goes away.
......@@ -80,9 +65,8 @@ xfs_synchronize_atime(
vp = XFS_ITOV_NULL(ip);
if (vp) {
struct inode *inode = &vp->v_inode;
ip->i_d.di_atime.t_sec = (__int32_t)inode->i_atime.tv_sec;
ip->i_d.di_atime.t_nsec = (__int32_t)inode->i_atime.tv_nsec;
ip->i_d.di_atime.t_sec = (__int32_t)vp->i_atime.tv_sec;
ip->i_d.di_atime.t_nsec = (__int32_t)vp->i_atime.tv_nsec;
}
}
......@@ -195,18 +179,19 @@ xfs_ichgtime_fast(
*/
STATIC void
xfs_validate_fields(
struct inode *ip,
bhv_vattr_t *vattr)
struct inode *inode)
{
vattr->va_mask = XFS_AT_NLINK|XFS_AT_SIZE|XFS_AT_NBLOCKS;
if (!bhv_vop_getattr(vn_from_inode(ip), vattr, ATTR_LAZY, NULL)) {
ip->i_nlink = vattr->va_nlink;
ip->i_blocks = vattr->va_nblocks;
/* we're under i_sem so i_size can't change under us */
if (i_size_read(ip) != vattr->va_size)
i_size_write(ip, vattr->va_size);
}
struct xfs_inode *ip = XFS_I(inode);
loff_t size;
inode->i_nlink = ip->i_d.di_nlink;
inode->i_blocks =
XFS_FSB_TO_BB(ip->i_mount, ip->i_d.di_nblocks +
ip->i_delayed_blks);
/* we're under i_sem so i_size can't change under us */
size = XFS_ISIZE(ip);
if (i_size_read(inode) != size)
i_size_write(inode, size);
}
/*
......@@ -233,9 +218,10 @@ xfs_init_security(
return -error;
}
error = bhv_vop_attr_set(vp, name, value, length, ATTR_SECURE, NULL);
error = xfs_attr_set(XFS_I(ip), name, value,
length, ATTR_SECURE);
if (!error)
VMODIFY(vp);
xfs_iflags_set(XFS_I(ip), XFS_IMODIFIED);
kfree(name);
kfree(value);
......@@ -256,7 +242,7 @@ xfs_has_fs_struct(struct task_struct *task)
STATIC void
xfs_cleanup_inode(
bhv_vnode_t *dvp,
struct inode *dir,
bhv_vnode_t *vp,
struct dentry *dentry,
int mode)
......@@ -272,9 +258,9 @@ xfs_cleanup_inode(
teardown.d_name = dentry->d_name;
if (S_ISDIR(mode))
bhv_vop_rmdir(dvp, &teardown, NULL);
xfs_rmdir(XFS_I(dir), &teardown);
else
bhv_vop_remove(dvp, &teardown, NULL);
xfs_remove(XFS_I(dir), &teardown);
VN_RELE(vp);
}
......@@ -286,7 +272,6 @@ xfs_vn_mknod(
dev_t rdev)
{
struct inode *ip;
bhv_vattr_t vattr = { 0 };
bhv_vnode_t *vp = NULL, *dvp = vn_from_inode(dir);
xfs_acl_t *default_acl = NULL;
attrexists_t test_default_acl = _ACL_DEFAULT_EXISTS;
......@@ -312,19 +297,14 @@ xfs_vn_mknod(
if (IS_POSIXACL(dir) && !default_acl && xfs_has_fs_struct(current))
mode &= ~current->fs->umask;
vattr.va_mask = XFS_AT_TYPE|XFS_AT_MODE;
vattr.va_mode = mode;
switch (mode & S_IFMT) {
case S_IFCHR: case S_IFBLK: case S_IFIFO: case S_IFSOCK:
vattr.va_rdev = sysv_encode_dev(rdev);
vattr.va_mask |= XFS_AT_RDEV;
/*FALLTHROUGH*/
rdev = sysv_encode_dev(rdev);
case S_IFREG:
error = bhv_vop_create(dvp, dentry, &vattr, &vp, NULL);
error = xfs_create(XFS_I(dir), dentry, mode, rdev, &vp, NULL);
break;
case S_IFDIR:
error = bhv_vop_mkdir(dvp, dentry, &vattr, &vp, NULL);
error = xfs_mkdir(XFS_I(dir), dentry, mode, &vp, NULL);
break;
default:
error = EINVAL;
......@@ -334,16 +314,16 @@ xfs_vn_mknod(
if (unlikely(!error)) {
error = xfs_init_security(vp, dir);
if (error)
xfs_cleanup_inode(dvp, vp, dentry, mode);
xfs_cleanup_inode(dir, vp, dentry, mode);
}
if (unlikely(default_acl)) {
if (!error) {
error = _ACL_INHERIT(vp, &vattr, default_acl);
error = _ACL_INHERIT(vp, mode, default_acl);
if (!error)
VMODIFY(vp);
xfs_iflags_set(XFS_I(vp), XFS_IMODIFIED);
else
xfs_cleanup_inode(dvp, vp, dentry, mode);
xfs_cleanup_inode(dir, vp, dentry, mode);
}
_ACL_FREE(default_acl);
}
......@@ -355,9 +335,9 @@ xfs_vn_mknod(
if (S_ISCHR(mode) || S_ISBLK(mode))
ip->i_rdev = rdev;
else if (S_ISDIR(mode))
xfs_validate_fields(ip, &vattr);
xfs_validate_fields(ip);
d_instantiate(dentry, ip);
xfs_validate_fields(dir, &vattr);
xfs_validate_fields(dir);
}
return -error;
}
......@@ -387,13 +367,13 @@ xfs_vn_lookup(
struct dentry *dentry,
struct nameidata *nd)
{
bhv_vnode_t *vp = vn_from_inode(dir), *cvp;
bhv_vnode_t *cvp;
int error;
if (dentry->d_name.len >= MAXNAMELEN)
return ERR_PTR(-ENAMETOOLONG);
error = bhv_vop_lookup(vp, dentry, &cvp, 0, NULL, NULL);
error = xfs_lookup(XFS_I(dir), dentry, &cvp);
if (unlikely(error)) {
if (unlikely(error != ENOENT))
return ERR_PTR(-error);
......@@ -411,22 +391,19 @@ xfs_vn_link(
struct dentry *dentry)
{
struct inode *ip; /* inode of guy being linked to */
bhv_vnode_t *tdvp; /* target directory for new name/link */
bhv_vnode_t *vp; /* vp of name being linked */
bhv_vattr_t vattr;
int error;
ip = old_dentry->d_inode; /* inode being linked to */
tdvp = vn_from_inode(dir);
vp = vn_from_inode(ip);
VN_HOLD(vp);
error = bhv_vop_link(tdvp, vp, dentry, NULL);
error = xfs_link(XFS_I(dir), vp, dentry);
if (unlikely(error)) {
VN_RELE(vp);
} else {
VMODIFY(tdvp);
xfs_validate_fields(ip, &vattr);
xfs_iflags_set(XFS_I(dir), XFS_IMODIFIED);
xfs_validate_fields(ip);
d_instantiate(dentry, ip);
}
return -error;
......@@ -438,17 +415,14 @@ xfs_vn_unlink(
struct dentry *dentry)
{
struct inode *inode;
bhv_vnode_t *dvp; /* directory containing name to remove */
bhv_vattr_t vattr;
int error;
inode = dentry->d_inode;
dvp = vn_from_inode(dir);
error = bhv_vop_remove(dvp, dentry, NULL);
error = xfs_remove(XFS_I(dir), dentry);
if (likely(!error)) {
xfs_validate_fields(dir, &vattr); /* size needs update */
xfs_validate_fields(inode, &vattr);
xfs_validate_fields(dir); /* size needs update */
xfs_validate_fields(inode);
}
return -error;
}
......@@ -460,28 +434,26 @@ xfs_vn_symlink(
const char *symname)
{
struct inode *ip;
bhv_vattr_t va = { 0 };
bhv_vnode_t *dvp; /* directory containing name of symlink */
bhv_vnode_t *cvp; /* used to lookup symlink to put in dentry */
int error;
mode_t mode;
dvp = vn_from_inode(dir);
cvp = NULL;
va.va_mode = S_IFLNK |
mode = S_IFLNK |
(irix_symlink_mode ? 0777 & ~current->fs->umask : S_IRWXUGO);
va.va_mask = XFS_AT_TYPE|XFS_AT_MODE;
error = bhv_vop_symlink(dvp, dentry, &va, (char *)symname, &cvp, NULL);
error = xfs_symlink(XFS_I(dir), dentry, (char *)symname, mode,
&cvp, NULL);
if (likely(!error && cvp)) {
error = xfs_init_security(cvp, dir);
if (likely(!error)) {
ip = vn_to_inode(cvp);
d_instantiate(dentry, ip);
xfs_validate_fields(dir, &va);
xfs_validate_fields(ip, &va);
xfs_validate_fields(dir);
xfs_validate_fields(ip);
} else {
xfs_cleanup_inode(dvp, cvp, dentry, 0);
xfs_cleanup_inode(dir, cvp, dentry, 0);
}
}
return -error;
......@@ -493,14 +465,12 @@ xfs_vn_rmdir(
struct dentry *dentry)
{
struct inode *inode = dentry->d_inode;
bhv_vnode_t *dvp = vn_from_inode(dir);
bhv_vattr_t vattr;
int error;
error = bhv_vop_rmdir(dvp, dentry, NULL);
error = xfs_rmdir(XFS_I(dir), dentry);
if (likely(!error)) {
xfs_validate_fields(inode, &vattr);
xfs_validate_fields(dir, &vattr);
xfs_validate_fields(inode);
xfs_validate_fields(dir);
}
return -error;
}
......@@ -513,21 +483,18 @@ xfs_vn_rename(
struct dentry *ndentry)
{
struct inode *new_inode = ndentry->d_inode;
bhv_vnode_t *fvp; /* from directory */
bhv_vnode_t *tvp; /* target directory */
bhv_vattr_t vattr;
int error;
fvp = vn_from_inode(odir);
tvp = vn_from_inode(ndir);
error = bhv_vop_rename(fvp, odentry, tvp, ndentry, NULL);
error = xfs_rename(XFS_I(odir), odentry, tvp, ndentry);
if (likely(!error)) {
if (new_inode)
xfs_validate_fields(new_inode, &vattr);
xfs_validate_fields(odir, &vattr);
xfs_validate_fields(new_inode);
xfs_validate_fields(odir);
if (ndir != odir)
xfs_validate_fields(ndir, &vattr);
xfs_validate_fields(ndir);
}
return -error;
}
......@@ -542,50 +509,25 @@ xfs_vn_follow_link(
struct dentry *dentry,
struct nameidata *nd)
{
bhv_vnode_t *vp;
uio_t *uio;
iovec_t iov;
int error;
char *link;
ASSERT(dentry);
ASSERT(nd);
int error = -ENOMEM;
link = kmalloc(MAXPATHLEN+1, GFP_KERNEL);
if (!link) {
nd_set_link(nd, ERR_PTR(-ENOMEM));
return NULL;
}
uio = kmalloc(sizeof(uio_t), GFP_KERNEL);
if (!uio) {
kfree(link);
nd_set_link(nd, ERR_PTR(-ENOMEM));
return NULL;
}
vp = vn_from_inode(dentry->d_inode);
iov.iov_base = link;
iov.iov_len = MAXPATHLEN;
if (!link)
goto out_err;
uio->uio_iov = &iov;
uio->uio_offset = 0;
uio->uio_segflg = UIO_SYSSPACE;
uio->uio_resid = MAXPATHLEN;
uio->uio_iovcnt = 1;
error = bhv_vop_readlink(vp, uio, 0, NULL);
if (unlikely(error)) {
kfree(link);
link = ERR_PTR(-error);
} else {
link[MAXPATHLEN - uio->uio_resid] = '\0';
}
kfree(uio);
error = -xfs_readlink(XFS_I(dentry->d_inode), link);
if (unlikely(error))
goto out_kfree;
nd_set_link(nd, link);
return NULL;
out_kfree:
kfree(link);
out_err:
nd_set_link(nd, ERR_PTR(error));
return NULL;
}
STATIC void
......@@ -607,7 +549,7 @@ xfs_vn_permission(
int mode,
struct nameidata *nd)
{
return -bhv_vop_access(vn_from_inode(inode), mode << 6, NULL);
return -xfs_access(XFS_I(inode), mode << 6, NULL);
}
#else
#define xfs_vn_permission NULL
......@@ -620,11 +562,10 @@ xfs_vn_getattr(
struct kstat *stat)
{
struct inode *inode = dentry->d_inode;
bhv_vnode_t *vp = vn_from_inode(inode);
bhv_vattr_t vattr = { .va_mask = XFS_AT_STAT };
int error;
error = bhv_vop_getattr(vp, &vattr, ATTR_LAZY, NULL);
error = xfs_getattr(XFS_I(inode), &vattr, ATTR_LAZY);
if (likely(!error)) {
stat->size = i_size_read(inode);
stat->dev = inode->i_sb->s_dev;
......@@ -652,7 +593,6 @@ xfs_vn_setattr(
{
struct inode *inode = dentry->d_inode;
unsigned int ia_valid = attr->ia_valid;
bhv_vnode_t *vp = vn_from_inode(inode);
bhv_vattr_t vattr = { 0 };
int flags = 0;
int error;
......@@ -696,9 +636,9 @@ xfs_vn_setattr(
flags |= ATTR_NONBLOCK;
#endif
error = bhv_vop_setattr(vp, &vattr, flags, NULL);
error = xfs_setattr(XFS_I(inode), &vattr, flags, NULL);
if (likely(!error))
__vn_revalidate(vp, &vattr);
__vn_revalidate(vn_from_inode(inode), &vattr);
return -error;
}
......
......@@ -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__ */
......@@ -46,6 +46,8 @@
#include "xfs_attr.h"
#include "xfs_buf_item.h"
#include "xfs_utils.h"
#include "xfs_vnodeops.h"
#include "xfs_vfsops.h"
#include "xfs_version.h"
#include <linux/namei.h>
......@@ -196,23 +198,20 @@ xfs_revalidate_inode(
inode->i_flags |= S_NOATIME;
else
inode->i_flags &= ~S_NOATIME;
vp->v_flag &= ~VMODIFIED;
xfs_iflags_clear(ip, XFS_IMODIFIED);
}
void
xfs_initialize_vnode(
bhv_desc_t *bdp,
struct xfs_mount *mp,
bhv_vnode_t *vp,
bhv_desc_t *inode_bhv,
int unlock)
struct xfs_inode *ip)
{
xfs_inode_t *ip = XFS_BHVTOI(inode_bhv);
struct inode *inode = vn_to_inode(vp);
if (!inode_bhv->bd_vobj) {
vp->v_vfsp = bhvtovfs(bdp);
bhv_desc_init(inode_bhv, ip, vp, &xfs_vnodeops);
bhv_insert(VN_BHV_HEAD(vp), inode_bhv);
if (!ip->i_vnode) {
ip->i_vnode = vp;
inode->i_private = ip;
}
/*
......@@ -222,8 +221,8 @@ xfs_initialize_vnode(
* second time once the inode is properly set up, and then we can
* finish our work.
*/
if (ip->i_d.di_mode != 0 && unlock && (inode->i_state & I_NEW)) {
xfs_revalidate_inode(XFS_BHVTOM(bdp), vp, ip);
if (ip->i_d.di_mode != 0 && (inode->i_state & I_NEW)) {
xfs_revalidate_inode(mp, vp, ip);
xfs_set_inodeops(inode);
xfs_iflags_clear(ip, XFS_INEW);
......@@ -409,19 +408,22 @@ xfs_fs_write_inode(
struct inode *inode,
int sync)
{
bhv_vnode_t *vp = vn_from_inode(inode);
int error = 0, flags = FLUSH_INODE;
if (vp) {
vn_trace_entry(vp, __FUNCTION__, (inst_t *)__return_address);
if (sync) {
filemap_fdatawait(inode->i_mapping);
flags |= FLUSH_SYNC;
}
error = bhv_vop_iflush(vp, flags);
if (error == EAGAIN)
error = sync? bhv_vop_iflush(vp, flags | FLUSH_LOG) : 0;
vn_trace_entry(XFS_I(inode), __FUNCTION__,
(inst_t *)__return_address);
if (sync) {
filemap_fdatawait(inode->i_mapping);
flags |= FLUSH_SYNC;
}
error = xfs_inode_flush(XFS_I(inode), flags);
/*
* if we failed to write out the inode then mark
* it dirty again so we'll try again later.
*/
if (error)
mark_inode_dirty_sync(inode);
return -error;
}
......@@ -429,35 +431,27 @@ STATIC void
xfs_fs_clear_inode(
struct inode *inode)
{
bhv_vnode_t *vp = vn_from_inode(inode);
vn_trace_entry(vp, __FUNCTION__, (inst_t *)__return_address);
XFS_STATS_INC(vn_rele);
XFS_STATS_INC(vn_remove);
XFS_STATS_INC(vn_reclaim);
XFS_STATS_DEC(vn_active);
xfs_inode_t *ip = XFS_I(inode);
/*
* This can happen because xfs_iget_core calls xfs_idestroy if we
* ip can be null when xfs_iget_core calls xfs_idestroy if we
* find an inode with di_mode == 0 but without IGET_CREATE set.
*/
if (VNHEAD(vp))
bhv_vop_inactive(vp, NULL);
VN_LOCK(vp);
vp->v_flag &= ~VMODIFIED;
VN_UNLOCK(vp, 0);
if (VNHEAD(vp))
if (bhv_vop_reclaim(vp))
panic("%s: cannot reclaim 0x%p\n", __FUNCTION__, vp);
ASSERT(VNHEAD(vp) == NULL);
if (ip) {
vn_trace_entry(ip, __FUNCTION__, (inst_t *)__return_address);
XFS_STATS_INC(vn_rele);
XFS_STATS_INC(vn_remove);
XFS_STATS_INC(vn_reclaim);
XFS_STATS_DEC(vn_active);
xfs_inactive(ip);
xfs_iflags_clear(ip, XFS_IMODIFIED);
if (xfs_reclaim(ip))
panic("%s: cannot reclaim 0x%p\n", __FUNCTION__, inode);
}
#ifdef XFS_VNODE_TRACE
ktrace_free(vp->v_trace);
#endif
ASSERT(XFS_I(inode) == NULL);
}
/*
......@@ -469,9 +463,9 @@ xfs_fs_clear_inode(
*/
STATIC void
xfs_syncd_queue_work(
struct bhv_vfs *vfs,
struct xfs_mount *mp,
void *data,
void (*syncer)(bhv_vfs_t *, void *))
void (*syncer)(struct xfs_mount *, void *))
{
struct bhv_vfs_sync_work *work;
......@@ -479,11 +473,11 @@ xfs_syncd_queue_work(
INIT_LIST_HEAD(&work->w_list);
work->w_syncer = syncer;
work->w_data = data;
work->w_vfs = vfs;
spin_lock(&vfs->vfs_sync_lock);
list_add_tail(&work->w_list, &vfs->vfs_sync_list);
spin_unlock(&vfs->vfs_sync_lock);
wake_up_process(vfs->vfs_sync_task);
work->w_mount = mp;
spin_lock(&mp->m_sync_lock);
list_add_tail(&work->w_list, &mp->m_sync_list);
spin_unlock(&mp->m_sync_lock);
wake_up_process(mp->m_sync_task);
}
/*
......@@ -494,22 +488,22 @@ xfs_syncd_queue_work(
*/
STATIC void
xfs_flush_inode_work(
bhv_vfs_t *vfs,
void *inode)
struct xfs_mount *mp,
void *arg)
{
filemap_flush(((struct inode *)inode)->i_mapping);
iput((struct inode *)inode);
struct inode *inode = arg;
filemap_flush(inode->i_mapping);
iput(inode);
}
void
xfs_flush_inode(
xfs_inode_t *ip)
{
struct inode *inode = vn_to_inode(XFS_ITOV(ip));
struct bhv_vfs *vfs = XFS_MTOVFS(ip->i_mount);
struct inode *inode = ip->i_vnode;
igrab(inode);
xfs_syncd_queue_work(vfs, inode, xfs_flush_inode_work);
xfs_syncd_queue_work(ip->i_mount, inode, xfs_flush_inode_work);
delay(msecs_to_jiffies(500));
}
......@@ -519,11 +513,12 @@ xfs_flush_inode(
*/
STATIC void
xfs_flush_device_work(
bhv_vfs_t *vfs,
void *inode)
struct xfs_mount *mp,
void *arg)
{
sync_blockdev(vfs->vfs_super->s_bdev);
iput((struct inode *)inode);
struct inode *inode = arg;
sync_blockdev(mp->m_super->s_bdev);
iput(inode);
}
void
......@@ -531,35 +526,33 @@ xfs_flush_device(
xfs_inode_t *ip)
{
struct inode *inode = vn_to_inode(XFS_ITOV(ip));
struct bhv_vfs *vfs = XFS_MTOVFS(ip->i_mount);
igrab(inode);
xfs_syncd_queue_work(vfs, inode, xfs_flush_device_work);
xfs_syncd_queue_work(ip->i_mount, inode, xfs_flush_device_work);
delay(msecs_to_jiffies(500));
xfs_log_force(ip->i_mount, (xfs_lsn_t)0, XFS_LOG_FORCE|XFS_LOG_SYNC);
}
STATIC void
vfs_sync_worker(
bhv_vfs_t *vfsp,
xfs_sync_worker(
struct xfs_mount *mp,
void *unused)
{
int error;
if (!(vfsp->vfs_flag & VFS_RDONLY))
error = bhv_vfs_sync(vfsp, SYNC_FSDATA | SYNC_BDFLUSH | \
SYNC_ATTR | SYNC_REFCACHE | SYNC_SUPER,
NULL);
vfsp->vfs_sync_seq++;
wake_up(&vfsp->vfs_wait_single_sync_task);
if (!(mp->m_flags & XFS_MOUNT_RDONLY))
error = xfs_sync(mp, SYNC_FSDATA | SYNC_BDFLUSH | SYNC_ATTR |
SYNC_REFCACHE | SYNC_SUPER);
mp->m_sync_seq++;
wake_up(&mp->m_wait_single_sync_task);
}
STATIC int
xfssyncd(
void *arg)
{
struct xfs_mount *mp = arg;
long timeleft;
bhv_vfs_t *vfsp = (bhv_vfs_t *) arg;
bhv_vfs_sync_work_t *work, *n;
LIST_HEAD (tmp);
......@@ -569,31 +562,31 @@ xfssyncd(
timeleft = schedule_timeout_interruptible(timeleft);
/* swsusp */
try_to_freeze();
if (kthread_should_stop() && list_empty(&vfsp->vfs_sync_list))
if (kthread_should_stop() && list_empty(&mp->m_sync_list))
break;
spin_lock(&vfsp->vfs_sync_lock);
spin_lock(&mp->m_sync_lock);
/*
* We can get woken by laptop mode, to do a sync -
* that's the (only!) case where the list would be
* empty with time remaining.
*/
if (!timeleft || list_empty(&vfsp->vfs_sync_list)) {
if (!timeleft || list_empty(&mp->m_sync_list)) {
if (!timeleft)
timeleft = xfs_syncd_centisecs *
msecs_to_jiffies(10);
INIT_LIST_HEAD(&vfsp->vfs_sync_work.w_list);
list_add_tail(&vfsp->vfs_sync_work.w_list,
&vfsp->vfs_sync_list);
INIT_LIST_HEAD(&mp->m_sync_work.w_list);
list_add_tail(&mp->m_sync_work.w_list,
&mp->m_sync_list);
}
list_for_each_entry_safe(work, n, &vfsp->vfs_sync_list, w_list)
list_for_each_entry_safe(work, n, &mp->m_sync_list, w_list)
list_move(&work->w_list, &tmp);
spin_unlock(&vfsp->vfs_sync_lock);
spin_unlock(&mp->m_sync_lock);
list_for_each_entry_safe(work, n, &tmp, w_list) {
(*work->w_syncer)(vfsp, work->w_data);
(*work->w_syncer)(mp, work->w_data);
list_del(&work->w_list);
if (work == &vfsp->vfs_sync_work)
if (work == &mp->m_sync_work)
continue;
kmem_free(work, sizeof(struct bhv_vfs_sync_work));
}
......@@ -602,41 +595,19 @@ xfssyncd(
return 0;
}
STATIC int
xfs_fs_start_syncd(
bhv_vfs_t *vfsp)
{
vfsp->vfs_sync_work.w_syncer = vfs_sync_worker;
vfsp->vfs_sync_work.w_vfs = vfsp;
vfsp->vfs_sync_task = kthread_run(xfssyncd, vfsp, "xfssyncd");
if (IS_ERR(vfsp->vfs_sync_task))
return -PTR_ERR(vfsp->vfs_sync_task);
return 0;
}
STATIC void
xfs_fs_stop_syncd(
bhv_vfs_t *vfsp)
{
kthread_stop(vfsp->vfs_sync_task);
}
STATIC void
xfs_fs_put_super(
struct super_block *sb)
{
bhv_vfs_t *vfsp = vfs_from_sb(sb);
struct xfs_mount *mp = XFS_M(sb);
int error;
xfs_fs_stop_syncd(vfsp);
bhv_vfs_sync(vfsp, SYNC_ATTR | SYNC_DELWRI, NULL);
error = bhv_vfs_unmount(vfsp, 0, NULL);
if (error) {
kthread_stop(mp->m_sync_task);
xfs_sync(mp, SYNC_ATTR | SYNC_DELWRI);
error = xfs_unmount(mp, 0, NULL);
if (error)
printk("XFS: unmount got error=%d\n", error);
printk("%s: vfs=0x%p left dangling!\n", __FUNCTION__, vfsp);
} else {
vfs_deallocate(vfsp);
}
}
STATIC void
......@@ -644,7 +615,7 @@ xfs_fs_write_super(
struct super_block *sb)
{
if (!(sb->s_flags & MS_RDONLY))
bhv_vfs_sync(vfs_from_sb(sb), SYNC_FSDATA, NULL);
xfs_sync(XFS_M(sb), SYNC_FSDATA);
sb->s_dirt = 0;
}
......@@ -653,11 +624,23 @@ xfs_fs_sync_super(
struct super_block *sb,
int wait)
{
bhv_vfs_t *vfsp = vfs_from_sb(sb);
struct xfs_mount *mp = XFS_M(sb);
int error;
int flags;
if (unlikely(sb->s_frozen == SB_FREEZE_WRITE)) {
/*
* Treat a sync operation like a freeze. This is to work
* around a race in sync_inodes() which works in two phases
* - an asynchronous flush, which can write out an inode
* without waiting for file size updates to complete, and a
* synchronous flush, which wont do anything because the
* async flush removed the inode's dirty flag. Also
* sync_inodes() will not see any files that just have
* outstanding transactions to be flushed because we don't
* dirty the Linux inode until after the transaction I/O
* completes.
*/
if (wait || unlikely(sb->s_frozen == SB_FREEZE_WRITE)) {
/*
* First stage of freeze - no more writers will make progress
* now we are here, so we flush delwri and delalloc buffers
......@@ -668,28 +651,28 @@ xfs_fs_sync_super(
*/
flags = SYNC_DATA_QUIESCE;
} else
flags = SYNC_FSDATA | (wait ? SYNC_WAIT : 0);
flags = SYNC_FSDATA;
error = bhv_vfs_sync(vfsp, flags, NULL);
error = xfs_sync(mp, flags);
sb->s_dirt = 0;
if (unlikely(laptop_mode)) {
int prev_sync_seq = vfsp->vfs_sync_seq;
int prev_sync_seq = mp->m_sync_seq;
/*
* The disk must be active because we're syncing.
* We schedule xfssyncd now (now that the disk is
* active) instead of later (when it might not be).
*/
wake_up_process(vfsp->vfs_sync_task);
wake_up_process(mp->m_sync_task);
/*
* We have to wait for the sync iteration to complete.
* If we don't, the disk activity caused by the sync
* will come after the sync is completed, and that
* triggers another sync from laptop mode.
*/
wait_event(vfsp->vfs_wait_single_sync_task,
vfsp->vfs_sync_seq != prev_sync_seq);
wait_event(mp->m_wait_single_sync_task,
mp->m_sync_seq != prev_sync_seq);
}
return -error;
......@@ -700,7 +683,7 @@ xfs_fs_statfs(
struct dentry *dentry,
struct kstatfs *statp)
{
return -bhv_vfs_statvfs(vfs_from_sb(dentry->d_sb), statp,
return -xfs_statvfs(XFS_M(dentry->d_sb), statp,
vn_from_inode(dentry->d_inode));
}
......@@ -710,13 +693,13 @@ xfs_fs_remount(
int *flags,
char *options)
{
bhv_vfs_t *vfsp = vfs_from_sb(sb);
struct xfs_mount *mp = XFS_M(sb);
struct xfs_mount_args *args = xfs_args_allocate(sb, 0);
int error;
error = bhv_vfs_parseargs(vfsp, options, args, 1);
error = xfs_parseargs(mp, options, args, 1);
if (!error)
error = bhv_vfs_mntupdate(vfsp, flags, args);
error = xfs_mntupdate(mp, flags, args);
kmem_free(args, sizeof(*args));
return -error;
}
......@@ -725,7 +708,7 @@ STATIC void
xfs_fs_lockfs(
struct super_block *sb)
{
bhv_vfs_freeze(vfs_from_sb(sb));
xfs_freeze(XFS_M(sb));
}
STATIC int
......@@ -733,7 +716,7 @@ xfs_fs_show_options(
struct seq_file *m,
struct vfsmount *mnt)
{
return -bhv_vfs_showargs(vfs_from_sb(mnt->mnt_sb), m);
return -xfs_showargs(XFS_M(mnt->mnt_sb), m);
}
STATIC int
......@@ -741,7 +724,7 @@ xfs_fs_quotasync(
struct super_block *sb,
int type)
{
return -bhv_vfs_quotactl(vfs_from_sb(sb), Q_XQUOTASYNC, 0, NULL);
return -XFS_QM_QUOTACTL(XFS_M(sb), Q_XQUOTASYNC, 0, NULL);
}
STATIC int
......@@ -749,7 +732,7 @@ xfs_fs_getxstate(
struct super_block *sb,
struct fs_quota_stat *fqs)
{
return -bhv_vfs_quotactl(vfs_from_sb(sb), Q_XGETQSTAT, 0, (caddr_t)fqs);
return -XFS_QM_QUOTACTL(XFS_M(sb), Q_XGETQSTAT, 0, (caddr_t)fqs);
}
STATIC int
......@@ -758,7 +741,7 @@ xfs_fs_setxstate(
unsigned int flags,
int op)
{
return -bhv_vfs_quotactl(vfs_from_sb(sb), op, 0, (caddr_t)&flags);
return -XFS_QM_QUOTACTL(XFS_M(sb), op, 0, (caddr_t)&flags);
}
STATIC int
......@@ -768,7 +751,7 @@ xfs_fs_getxquota(
qid_t id,
struct fs_disk_quota *fdq)
{
return -bhv_vfs_quotactl(vfs_from_sb(sb),
return -XFS_QM_QUOTACTL(XFS_M(sb),
(type == USRQUOTA) ? Q_XGETQUOTA :
((type == GRPQUOTA) ? Q_XGETGQUOTA :
Q_XGETPQUOTA), id, (caddr_t)fdq);
......@@ -781,7 +764,7 @@ xfs_fs_setxquota(
qid_t id,
struct fs_disk_quota *fdq)
{
return -bhv_vfs_quotactl(vfs_from_sb(sb),
return -XFS_QM_QUOTACTL(XFS_M(sb),
(type == USRQUOTA) ? Q_XSETQLIM :
((type == GRPQUOTA) ? Q_XSETGQLIM :
Q_XSETPQLIM), id, (caddr_t)fdq);
......@@ -793,32 +776,38 @@ xfs_fs_fill_super(
void *data,
int silent)
{
struct bhv_vnode *rootvp;
struct bhv_vfs *vfsp = vfs_allocate(sb);
struct inode *rootvp;
struct xfs_mount *mp = NULL;
struct xfs_mount_args *args = xfs_args_allocate(sb, silent);
struct kstatfs statvfs;
int error;
bhv_insert_all_vfsops(vfsp);
mp = xfs_mount_init();
error = bhv_vfs_parseargs(vfsp, (char *)data, args, 0);
if (error) {
bhv_remove_all_vfsops(vfsp, 1);
INIT_LIST_HEAD(&mp->m_sync_list);
spin_lock_init(&mp->m_sync_lock);
init_waitqueue_head(&mp->m_wait_single_sync_task);
mp->m_super = sb;
sb->s_fs_info = mp;
if (sb->s_flags & MS_RDONLY)
mp->m_flags |= XFS_MOUNT_RDONLY;
error = xfs_parseargs(mp, (char *)data, args, 0);
if (error)
goto fail_vfsop;
}
sb_min_blocksize(sb, BBSIZE);
sb->s_export_op = &xfs_export_operations;
sb->s_qcop = &xfs_quotactl_operations;
sb->s_op = &xfs_super_operations;
error = bhv_vfs_mount(vfsp, args, NULL);
if (error) {
bhv_remove_all_vfsops(vfsp, 1);
error = xfs_mount(mp, args, NULL);
if (error)
goto fail_vfsop;
}
error = bhv_vfs_statvfs(vfsp, &statvfs, NULL);
error = xfs_statvfs(mp, &statvfs, NULL);
if (error)
goto fail_unmount;
......@@ -830,7 +819,7 @@ xfs_fs_fill_super(
sb->s_time_gran = 1;
set_posix_acl_flag(sb);
error = bhv_vfs_root(vfsp, &rootvp);
error = xfs_root(mp, &rootvp);
if (error)
goto fail_unmount;
......@@ -843,9 +832,17 @@ xfs_fs_fill_super(
error = EINVAL;
goto fail_vnrele;
}
if ((error = xfs_fs_start_syncd(vfsp)))
mp->m_sync_work.w_syncer = xfs_sync_worker;
mp->m_sync_work.w_mount = mp;
mp->m_sync_task = kthread_run(xfssyncd, mp, "xfssyncd");
if (IS_ERR(mp->m_sync_task)) {
error = -PTR_ERR(mp->m_sync_task);
goto fail_vnrele;
vn_trace_exit(rootvp, __FUNCTION__, (inst_t *)__return_address);
}
vn_trace_exit(XFS_I(sb->s_root->d_inode), __FUNCTION__,
(inst_t *)__return_address);
kmem_free(args, sizeof(*args));
return 0;
......@@ -859,10 +856,9 @@ xfs_fs_fill_super(
}
fail_unmount:
bhv_vfs_unmount(vfsp, 0, NULL);
xfs_unmount(mp, 0, NULL);
fail_vfsop:
vfs_deallocate(vfsp);
kmem_free(args, sizeof(*args));
return -error;
}
......@@ -914,15 +910,11 @@ STATIC int __init
init_xfs_fs( void )
{
int error;
struct sysinfo si;
static char message[] __initdata = KERN_INFO \
XFS_VERSION_STRING " with " XFS_BUILD_OPTIONS " enabled\n";
printk(message);
si_meminfo(&si);
xfs_physmem = si.totalram;
ktrace_init(64);
error = xfs_init_zones();
......
......@@ -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 */
......@@ -18,84 +18,31 @@
#ifndef __XFS_VNODE_H__
#define __XFS_VNODE_H__
struct uio;
struct file;
struct bhv_vfs;
struct bhv_vattr;
struct xfs_iomap;
struct attrlist_cursor_kern;
typedef struct dentry bhv_vname_t;
typedef __u64 bhv_vnumber_t;
typedef struct inode bhv_vnode_t;
typedef enum bhv_vflags {
VMODIFIED = 0x08, /* XFS inode state possibly differs */
/* to the Linux inode state. */
VTRUNCATED = 0x40, /* truncated down so flush-on-close */
} bhv_vflags_t;
/*
* MP locking protocols:
* v_flag, v_vfsp VN_LOCK/VN_UNLOCK
*/
typedef struct bhv_vnode {
bhv_vflags_t v_flag; /* vnode flags (see above) */
bhv_vfs_t *v_vfsp; /* ptr to containing VFS */
bhv_vnumber_t v_number; /* in-core vnode number */
bhv_head_t v_bh; /* behavior head */
spinlock_t v_lock; /* VN_LOCK/VN_UNLOCK */
atomic_t v_iocount; /* outstanding I/O count */
#ifdef XFS_VNODE_TRACE
struct ktrace *v_trace; /* trace header structure */
#endif
struct inode v_inode; /* Linux inode */
/* inode MUST be last */
} bhv_vnode_t;
#define VN_ISLNK(vp) S_ISLNK((vp)->v_inode.i_mode)
#define VN_ISREG(vp) S_ISREG((vp)->v_inode.i_mode)
#define VN_ISDIR(vp) S_ISDIR((vp)->v_inode.i_mode)
#define VN_ISCHR(vp) S_ISCHR((vp)->v_inode.i_mode)
#define VN_ISBLK(vp) S_ISBLK((vp)->v_inode.i_mode)
#define VNODE_POSITION_BASE BHV_POSITION_BASE /* chain bottom */
#define VNODE_POSITION_TOP BHV_POSITION_TOP /* chain top */
#define VNODE_POSITION_INVALID BHV_POSITION_INVALID /* invalid pos. num */
typedef enum {
VN_BHV_UNKNOWN, /* not specified */
VN_BHV_XFS, /* xfs */
VN_BHV_DM, /* data migration */
VN_BHV_QM, /* quota manager */
VN_BHV_IO, /* IO path */
VN_BHV_END /* housekeeping end-of-range */
} vn_bhv_t;
#define VNODE_POSITION_XFS (VNODE_POSITION_BASE)
#define VNODE_POSITION_DM (VNODE_POSITION_BASE+10)
#define VNODE_POSITION_QM (VNODE_POSITION_BASE+20)
#define VNODE_POSITION_IO (VNODE_POSITION_BASE+30)
/*
* Macros for dealing with the behavior descriptor inside of the vnode.
*/
#define BHV_TO_VNODE(bdp) ((bhv_vnode_t *)BHV_VOBJ(bdp))
#define BHV_TO_VNODE_NULL(bdp) ((bhv_vnode_t *)BHV_VOBJNULL(bdp))
#define VN_BHV_HEAD(vp) ((bhv_head_t *)(&((vp)->v_bh)))
#define vn_bhv_head_init(bhp,name) bhv_head_init(bhp,name)
#define vn_bhv_remove(bhp,bdp) bhv_remove(bhp,bdp)
#define VN_ISLNK(vp) S_ISLNK((vp)->i_mode)
#define VN_ISREG(vp) S_ISREG((vp)->i_mode)
#define VN_ISDIR(vp) S_ISDIR((vp)->i_mode)
#define VN_ISCHR(vp) S_ISCHR((vp)->i_mode)
#define VN_ISBLK(vp) S_ISBLK((vp)->i_mode)
/*
* Vnode to Linux inode mapping.
*/
static inline struct bhv_vnode *vn_from_inode(struct inode *inode)
static inline bhv_vnode_t *vn_from_inode(struct inode *inode)
{
return container_of(inode, bhv_vnode_t, v_inode);
return inode;
}
static inline struct inode *vn_to_inode(struct bhv_vnode *vnode)
static inline struct inode *vn_to_inode(bhv_vnode_t *vnode)
{
return &vnode->v_inode;
return vnode;
}
/*
......@@ -111,200 +58,13 @@ typedef enum bhv_vrwlock {
} bhv_vrwlock_t;
/*
* Return values for bhv_vop_inactive. A return value of
* Return values for xfs_inactive. A return value of
* VN_INACTIVE_NOCACHE implies that the file system behavior
* has disassociated its state and bhv_desc_t from the vnode.
*/
#define VN_INACTIVE_CACHE 0
#define VN_INACTIVE_NOCACHE 1
/*
* Values for the cmd code given to vop_vnode_change.
*/
typedef enum bhv_vchange {
VCHANGE_FLAGS_FRLOCKS = 0,
VCHANGE_FLAGS_ENF_LOCKING = 1,
VCHANGE_FLAGS_TRUNCATED = 2,
VCHANGE_FLAGS_PAGE_DIRTY = 3,
VCHANGE_FLAGS_IOEXCL_COUNT = 4
} bhv_vchange_t;
typedef int (*vop_open_t)(bhv_desc_t *, struct cred *);
typedef ssize_t (*vop_read_t)(bhv_desc_t *, struct kiocb *,
const struct iovec *, unsigned int,
loff_t *, int, struct cred *);
typedef ssize_t (*vop_write_t)(bhv_desc_t *, struct kiocb *,
const struct iovec *, unsigned int,
loff_t *, int, struct cred *);
typedef ssize_t (*vop_splice_read_t)(bhv_desc_t *, struct file *, loff_t *,
struct pipe_inode_info *, size_t, int, int,
struct cred *);
typedef ssize_t (*vop_splice_write_t)(bhv_desc_t *, struct pipe_inode_info *,
struct file *, loff_t *, size_t, int, int,
struct cred *);
typedef int (*vop_ioctl_t)(bhv_desc_t *, struct inode *, struct file *,
int, unsigned int, void __user *);
typedef int (*vop_getattr_t)(bhv_desc_t *, struct bhv_vattr *, int,
struct cred *);
typedef int (*vop_setattr_t)(bhv_desc_t *, struct bhv_vattr *, int,
struct cred *);
typedef int (*vop_access_t)(bhv_desc_t *, int, struct cred *);
typedef int (*vop_lookup_t)(bhv_desc_t *, bhv_vname_t *, bhv_vnode_t **,
int, bhv_vnode_t *, struct cred *);
typedef int (*vop_create_t)(bhv_desc_t *, bhv_vname_t *, struct bhv_vattr *,
bhv_vnode_t **, struct cred *);
typedef int (*vop_remove_t)(bhv_desc_t *, bhv_vname_t *, struct cred *);
typedef int (*vop_link_t)(bhv_desc_t *, bhv_vnode_t *, bhv_vname_t *,
struct cred *);
typedef int (*vop_rename_t)(bhv_desc_t *, bhv_vname_t *, bhv_vnode_t *,
bhv_vname_t *, struct cred *);
typedef int (*vop_mkdir_t)(bhv_desc_t *, bhv_vname_t *, struct bhv_vattr *,
bhv_vnode_t **, struct cred *);
typedef int (*vop_rmdir_t)(bhv_desc_t *, bhv_vname_t *, struct cred *);
typedef int (*vop_readdir_t)(bhv_desc_t *, struct uio *, struct cred *,
int *);
typedef int (*vop_symlink_t)(bhv_desc_t *, bhv_vname_t *, struct bhv_vattr*,
char *, bhv_vnode_t **, struct cred *);
typedef int (*vop_readlink_t)(bhv_desc_t *, struct uio *, int,
struct cred *);
typedef int (*vop_fsync_t)(bhv_desc_t *, int, struct cred *,
xfs_off_t, xfs_off_t);
typedef int (*vop_inactive_t)(bhv_desc_t *, struct cred *);
typedef int (*vop_fid2_t)(bhv_desc_t *, struct fid *);
typedef int (*vop_release_t)(bhv_desc_t *);
typedef int (*vop_rwlock_t)(bhv_desc_t *, bhv_vrwlock_t);
typedef void (*vop_rwunlock_t)(bhv_desc_t *, bhv_vrwlock_t);
typedef int (*vop_bmap_t)(bhv_desc_t *, xfs_off_t, ssize_t, int,
struct xfs_iomap *, int *);
typedef int (*vop_reclaim_t)(bhv_desc_t *);
typedef int (*vop_attr_get_t)(bhv_desc_t *, const char *, char *, int *,
int, struct cred *);
typedef int (*vop_attr_set_t)(bhv_desc_t *, const char *, char *, int,
int, struct cred *);
typedef int (*vop_attr_remove_t)(bhv_desc_t *, const char *,
int, struct cred *);
typedef int (*vop_attr_list_t)(bhv_desc_t *, char *, int, int,
struct attrlist_cursor_kern *, struct cred *);
typedef void (*vop_link_removed_t)(bhv_desc_t *, bhv_vnode_t *, int);
typedef void (*vop_vnode_change_t)(bhv_desc_t *, bhv_vchange_t, __psint_t);
typedef void (*vop_ptossvp_t)(bhv_desc_t *, xfs_off_t, xfs_off_t, int);
typedef int (*vop_pflushinvalvp_t)(bhv_desc_t *, xfs_off_t, xfs_off_t, int);
typedef int (*vop_pflushvp_t)(bhv_desc_t *, xfs_off_t, xfs_off_t,
uint64_t, int);
typedef int (*vop_iflush_t)(bhv_desc_t *, int);
typedef struct bhv_vnodeops {
bhv_position_t vn_position; /* position within behavior chain */
vop_open_t vop_open;
vop_read_t vop_read;
vop_write_t vop_write;
vop_splice_read_t vop_splice_read;
vop_splice_write_t vop_splice_write;
vop_ioctl_t vop_ioctl;
vop_getattr_t vop_getattr;
vop_setattr_t vop_setattr;
vop_access_t vop_access;
vop_lookup_t vop_lookup;
vop_create_t vop_create;
vop_remove_t vop_remove;
vop_link_t vop_link;
vop_rename_t vop_rename;
vop_mkdir_t vop_mkdir;
vop_rmdir_t vop_rmdir;
vop_readdir_t vop_readdir;
vop_symlink_t vop_symlink;
vop_readlink_t vop_readlink;
vop_fsync_t vop_fsync;
vop_inactive_t vop_inactive;
vop_fid2_t vop_fid2;
vop_rwlock_t vop_rwlock;
vop_rwunlock_t vop_rwunlock;
vop_bmap_t vop_bmap;
vop_reclaim_t vop_reclaim;
vop_attr_get_t vop_attr_get;
vop_attr_set_t vop_attr_set;
vop_attr_remove_t vop_attr_remove;
vop_attr_list_t vop_attr_list;
vop_link_removed_t vop_link_removed;
vop_vnode_change_t vop_vnode_change;
vop_ptossvp_t vop_tosspages;
vop_pflushinvalvp_t vop_flushinval_pages;
vop_pflushvp_t vop_flush_pages;
vop_release_t vop_release;
vop_iflush_t vop_iflush;
} bhv_vnodeops_t;
/*
* Virtual node operations, operating from head bhv.
*/
#define VNHEAD(vp) ((vp)->v_bh.bh_first)
#define VOP(op, vp) (*((bhv_vnodeops_t *)VNHEAD(vp)->bd_ops)->op)
#define bhv_vop_open(vp, cr) VOP(vop_open, vp)(VNHEAD(vp),cr)
#define bhv_vop_read(vp,file,iov,segs,offset,ioflags,cr) \
VOP(vop_read, vp)(VNHEAD(vp),file,iov,segs,offset,ioflags,cr)
#define bhv_vop_write(vp,file,iov,segs,offset,ioflags,cr) \
VOP(vop_write, vp)(VNHEAD(vp),file,iov,segs,offset,ioflags,cr)
#define bhv_vop_splice_read(vp,f,o,pipe,cnt,fl,iofl,cr) \
VOP(vop_splice_read, vp)(VNHEAD(vp),f,o,pipe,cnt,fl,iofl,cr)
#define bhv_vop_splice_write(vp,f,o,pipe,cnt,fl,iofl,cr) \
VOP(vop_splice_write, vp)(VNHEAD(vp),f,o,pipe,cnt,fl,iofl,cr)
#define bhv_vop_bmap(vp,of,sz,rw,b,n) \
VOP(vop_bmap, vp)(VNHEAD(vp),of,sz,rw,b,n)
#define bhv_vop_getattr(vp, vap,f,cr) \
VOP(vop_getattr, vp)(VNHEAD(vp), vap,f,cr)
#define bhv_vop_setattr(vp, vap,f,cr) \
VOP(vop_setattr, vp)(VNHEAD(vp), vap,f,cr)
#define bhv_vop_access(vp, mode,cr) VOP(vop_access, vp)(VNHEAD(vp), mode,cr)
#define bhv_vop_lookup(vp,d,vpp,f,rdir,cr) \
VOP(vop_lookup, vp)(VNHEAD(vp),d,vpp,f,rdir,cr)
#define bhv_vop_create(dvp,d,vap,vpp,cr) \
VOP(vop_create, dvp)(VNHEAD(dvp),d,vap,vpp,cr)
#define bhv_vop_remove(dvp,d,cr) VOP(vop_remove, dvp)(VNHEAD(dvp),d,cr)
#define bhv_vop_link(dvp,fvp,d,cr) VOP(vop_link, dvp)(VNHEAD(dvp),fvp,d,cr)
#define bhv_vop_rename(fvp,fnm,tdvp,tnm,cr) \
VOP(vop_rename, fvp)(VNHEAD(fvp),fnm,tdvp,tnm,cr)
#define bhv_vop_mkdir(dp,d,vap,vpp,cr) \
VOP(vop_mkdir, dp)(VNHEAD(dp),d,vap,vpp,cr)
#define bhv_vop_rmdir(dp,d,cr) VOP(vop_rmdir, dp)(VNHEAD(dp),d,cr)
#define bhv_vop_readdir(vp,uiop,cr,eofp) \
VOP(vop_readdir, vp)(VNHEAD(vp),uiop,cr,eofp)
#define bhv_vop_symlink(dvp,d,vap,tnm,vpp,cr) \
VOP(vop_symlink, dvp)(VNHEAD(dvp),d,vap,tnm,vpp,cr)
#define bhv_vop_readlink(vp,uiop,fl,cr) \
VOP(vop_readlink, vp)(VNHEAD(vp),uiop,fl,cr)
#define bhv_vop_fsync(vp,f,cr,b,e) VOP(vop_fsync, vp)(VNHEAD(vp),f,cr,b,e)
#define bhv_vop_inactive(vp,cr) VOP(vop_inactive, vp)(VNHEAD(vp),cr)
#define bhv_vop_release(vp) VOP(vop_release, vp)(VNHEAD(vp))
#define bhv_vop_fid2(vp,fidp) VOP(vop_fid2, vp)(VNHEAD(vp),fidp)
#define bhv_vop_rwlock(vp,i) VOP(vop_rwlock, vp)(VNHEAD(vp),i)
#define bhv_vop_rwlock_try(vp,i) VOP(vop_rwlock, vp)(VNHEAD(vp),i)
#define bhv_vop_rwunlock(vp,i) VOP(vop_rwunlock, vp)(VNHEAD(vp),i)
#define bhv_vop_frlock(vp,c,fl,flags,offset,fr) \
VOP(vop_frlock, vp)(VNHEAD(vp),c,fl,flags,offset,fr)
#define bhv_vop_reclaim(vp) VOP(vop_reclaim, vp)(VNHEAD(vp))
#define bhv_vop_attr_get(vp, name, val, vallenp, fl, cred) \
VOP(vop_attr_get, vp)(VNHEAD(vp),name,val,vallenp,fl,cred)
#define bhv_vop_attr_set(vp, name, val, vallen, fl, cred) \
VOP(vop_attr_set, vp)(VNHEAD(vp),name,val,vallen,fl,cred)
#define bhv_vop_attr_remove(vp, name, flags, cred) \
VOP(vop_attr_remove, vp)(VNHEAD(vp),name,flags,cred)
#define bhv_vop_attr_list(vp, buf, buflen, fl, cursor, cred) \
VOP(vop_attr_list, vp)(VNHEAD(vp),buf,buflen,fl,cursor,cred)
#define bhv_vop_link_removed(vp, dvp, linkzero) \
VOP(vop_link_removed, vp)(VNHEAD(vp), dvp, linkzero)
#define bhv_vop_vnode_change(vp, cmd, val) \
VOP(vop_vnode_change, vp)(VNHEAD(vp), cmd, val)
#define bhv_vop_toss_pages(vp, first, last, fiopt) \
VOP(vop_tosspages, vp)(VNHEAD(vp), first, last, fiopt)
#define bhv_vop_flushinval_pages(vp, first, last, fiopt) \
VOP(vop_flushinval_pages, vp)(VNHEAD(vp),first,last,fiopt)
#define bhv_vop_flush_pages(vp, first, last, flags, fiopt) \
VOP(vop_flush_pages, vp)(VNHEAD(vp),first,last,flags,fiopt)
#define bhv_vop_ioctl(vp, inode, filp, fl, cmd, arg) \
VOP(vop_ioctl, vp)(VNHEAD(vp),inode,filp,fl,cmd,arg)
#define bhv_vop_iflush(vp, flags) VOP(vop_iflush, vp)(VNHEAD(vp), flags)
/*
* Flags for read/write calls - same values as IRIX
*/
......@@ -428,16 +188,19 @@ typedef struct bhv_vattr {
extern void vn_init(void);
extern bhv_vnode_t *vn_initialize(struct inode *);
extern int vn_revalidate(struct bhv_vnode *);
extern int __vn_revalidate(struct bhv_vnode *, bhv_vattr_t *);
extern void vn_revalidate_core(struct bhv_vnode *, bhv_vattr_t *);
extern void vn_iowait(struct bhv_vnode *vp);
extern void vn_iowake(struct bhv_vnode *vp);
extern int vn_revalidate(bhv_vnode_t *);
extern int __vn_revalidate(bhv_vnode_t *, bhv_vattr_t *);
extern void vn_revalidate_core(bhv_vnode_t *, bhv_vattr_t *);
extern void vn_ioerror(struct bhv_vnode *vp, int error, char *f, int l);
/*
* Yeah, these don't take vnode anymore at all, all this should be
* cleaned up at some point.
*/
extern void vn_iowait(struct xfs_inode *ip);
extern void vn_iowake(struct xfs_inode *ip);
extern void vn_ioerror(struct xfs_inode *ip, int error, char *f, int l);
static inline int vn_count(struct bhv_vnode *vp)
static inline int vn_count(bhv_vnode_t *vp)
{
return atomic_read(&vn_to_inode(vp)->i_count);
}
......@@ -445,21 +208,21 @@ static inline int vn_count(struct bhv_vnode *vp)
/*
* Vnode reference counting functions (and macros for compatibility).
*/
extern bhv_vnode_t *vn_hold(struct bhv_vnode *);
extern bhv_vnode_t *vn_hold(bhv_vnode_t *);
#if defined(XFS_VNODE_TRACE)
#define VN_HOLD(vp) \
((void)vn_hold(vp), \
vn_trace_hold(vp, __FILE__, __LINE__, (inst_t *)__return_address))
vn_trace_hold(xfs_vtoi(vp), __FILE__, __LINE__, (inst_t *)__return_address))
#define VN_RELE(vp) \
(vn_trace_rele(vp, __FILE__, __LINE__, (inst_t *)__return_address), \
(vn_trace_rele(xfs_vtoi(vp), __FILE__, __LINE__, (inst_t *)__return_address), \
iput(vn_to_inode(vp)))
#else
#define VN_HOLD(vp) ((void)vn_hold(vp))
#define VN_RELE(vp) (iput(vn_to_inode(vp)))
#endif
static inline struct bhv_vnode *vn_grab(struct bhv_vnode *vp)
static inline bhv_vnode_t *vn_grab(bhv_vnode_t *vp)
{
struct inode *inode = igrab(vn_to_inode(vp));
return inode ? vn_from_inode(inode) : NULL;
......@@ -472,44 +235,15 @@ static inline struct bhv_vnode *vn_grab(struct bhv_vnode *vp)
#define VNAMELEN(dentry) ((dentry)->d_name.len)
#define VNAME_TO_VNODE(dentry) (vn_from_inode((dentry)->d_inode))
/*
* Vnode spinlock manipulation.
*/
#define VN_LOCK(vp) mutex_spinlock(&(vp)->v_lock)
#define VN_UNLOCK(vp, s) mutex_spinunlock(&(vp)->v_lock, s)
STATIC_INLINE void vn_flagset(struct bhv_vnode *vp, uint flag)
{
spin_lock(&vp->v_lock);
vp->v_flag |= flag;
spin_unlock(&vp->v_lock);
}
STATIC_INLINE uint vn_flagclr(struct bhv_vnode *vp, uint flag)
{
uint cleared;
spin_lock(&vp->v_lock);
cleared = (vp->v_flag & flag);
vp->v_flag &= ~flag;
spin_unlock(&vp->v_lock);
return cleared;
}
#define VMODIFY(vp) vn_flagset(vp, VMODIFIED)
#define VUNMODIFY(vp) vn_flagclr(vp, VMODIFIED)
#define VTRUNCATE(vp) vn_flagset(vp, VTRUNCATED)
#define VUNTRUNCATE(vp) vn_flagclr(vp, VTRUNCATED)
/*
* Dealing with bad inodes
*/
static inline void vn_mark_bad(struct bhv_vnode *vp)
static inline void vn_mark_bad(bhv_vnode_t *vp)
{
make_bad_inode(vn_to_inode(vp));
}
static inline int VN_BAD(struct bhv_vnode *vp)
static inline int VN_BAD(bhv_vnode_t *vp)
{
return is_bad_inode(vn_to_inode(vp));
}
......@@ -519,18 +253,18 @@ static inline int VN_BAD(struct bhv_vnode *vp)
*/
static inline void vn_atime_to_bstime(bhv_vnode_t *vp, xfs_bstime_t *bs_atime)
{
bs_atime->tv_sec = vp->v_inode.i_atime.tv_sec;
bs_atime->tv_nsec = vp->v_inode.i_atime.tv_nsec;
bs_atime->tv_sec = vp->i_atime.tv_sec;
bs_atime->tv_nsec = vp->i_atime.tv_nsec;
}
static inline void vn_atime_to_timespec(bhv_vnode_t *vp, struct timespec *ts)
{
*ts = vp->v_inode.i_atime;
*ts = vp->i_atime;
}
static inline void vn_atime_to_time_t(bhv_vnode_t *vp, time_t *tt)
{
*tt = vp->v_inode.i_atime.tv_sec;
*tt = vp->i_atime.tv_sec;
}
/*
......@@ -540,7 +274,6 @@ static inline void vn_atime_to_time_t(bhv_vnode_t *vp, time_t *tt)
#define VN_CACHED(vp) (vn_to_inode(vp)->i_mapping->nrpages)
#define VN_DIRTY(vp) mapping_tagged(vn_to_inode(vp)->i_mapping, \
PAGECACHE_TAG_DIRTY)
#define VN_TRUNC(vp) ((vp)->v_flag & VTRUNCATED)
/*
* Flags to vop_setattr/getattr.
......@@ -572,21 +305,17 @@ static inline void vn_atime_to_time_t(bhv_vnode_t *vp, time_t *tt)
#define VNODE_KTRACE_REF 4
#define VNODE_KTRACE_RELE 5
extern void vn_trace_entry(struct bhv_vnode *, const char *, inst_t *);
extern void vn_trace_exit(struct bhv_vnode *, const char *, inst_t *);
extern void vn_trace_hold(struct bhv_vnode *, char *, int, inst_t *);
extern void vn_trace_ref(struct bhv_vnode *, char *, int, inst_t *);
extern void vn_trace_rele(struct bhv_vnode *, char *, int, inst_t *);
#define VN_TRACE(vp) \
vn_trace_ref(vp, __FILE__, __LINE__, (inst_t *)__return_address)
extern void vn_trace_entry(struct xfs_inode *, const char *, inst_t *);
extern void vn_trace_exit(struct xfs_inode *, const char *, inst_t *);
extern void vn_trace_hold(struct xfs_inode *, char *, int, inst_t *);
extern void vn_trace_ref(struct xfs_inode *, char *, int, inst_t *);
extern void vn_trace_rele(struct xfs_inode *, char *, int, inst_t *);
#else
#define vn_trace_entry(a,b,c)
#define vn_trace_exit(a,b,c)
#define vn_trace_hold(a,b,c,d)
#define vn_trace_ref(a,b,c,d)
#define vn_trace_rele(a,b,c,d)
#define VN_TRACE(vp)
#endif
#endif /* __XFS_VNODE_H__ */
......@@ -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__ */
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册