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
  ...
This commit is contained in:
Linus Torvalds 2007-10-17 09:04:11 -07:00
commit 347c53dca7
90 changed files with 2777 additions and 4754 deletions

View file

@ -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

View file

@ -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);
}

View file

@ -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 */

View file

@ -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);

View file

@ -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);

View file

@ -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;
struct inode *inode = filp->f_path.dentry->d_inode;
xfs_inode_t *ip = XFS_I(inode);
int error;
size_t bufsize;
/* Try fairly hard to get memory */
do {
if ((read_buf = kmalloc(rlen, GFP_KERNEL)))
break;
rlen >>= 1;
} while (rlen >= 1024);
/*
* 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);
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;
}
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 */

View file

@ -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;
}

View file

@ -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__ */

View file

@ -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.

View file

@ -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__ */

View file

@ -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;

View file

@ -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;
}

View file

@ -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;
struct xfs_inode *ip = XFS_I(inode);
loff_t size;
/* 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);
}
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;
}
if (!link)
goto out_err;
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;
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;
}

View file

@ -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__ */

View file

@ -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>

View file

@ -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 @@ out_lock:
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 @@ start:
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 @@ start:
*/
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 @@ retry:
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 @@ retry:
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 @@ retry:
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 @@ retry:
/* 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 @@ retry:
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);

View file

@ -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__ */

View file

@ -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);
if (ip) {
vn_trace_entry(ip, __FUNCTION__, (inst_t *)__return_address);
VN_LOCK(vp);
vp->v_flag &= ~VMODIFIED;
VN_UNLOCK(vp, 0);
XFS_STATS_INC(vn_rele);
XFS_STATS_INC(vn_remove);
XFS_STATS_INC(vn_reclaim);
XFS_STATS_DEC(vn_active);
if (VNHEAD(vp))
if (bhv_vop_reclaim(vp))
panic("%s: cannot reclaim 0x%p\n", __FUNCTION__, vp);
xfs_inactive(ip);
xfs_iflags_clear(ip, XFS_IMODIFIED);
if (xfs_reclaim(ip))
panic("%s: cannot reclaim 0x%p\n", __FUNCTION__, inode);
}
ASSERT(VNHEAD(vp) == NULL);
#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 @@ fail_vnrele:
}
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();

View file

@ -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__ */

View file

@ -1,327 +0,0 @@
/*
* 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);
}

View file

@ -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__ */

View file

@ -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 */

View file

@ -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 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_iowait(struct bhv_vnode *vp);
extern void vn_iowake(struct bhv_vnode *vp);
/*
* 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);
extern void vn_ioerror(struct bhv_vnode *vp, 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__ */

View file

@ -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;
/*

View file

@ -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 *);

View file

@ -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)
{
struct bhv_vfs *vfsp = bhvtovfs(bhv);
struct xfs_mount *mp = XFS_VFSTOM(vfsp);
int error;
/*
* Get the Quota Manager to flush the dquots.
*/
if (XFS_IS_QUOTA_ON(mp)) {
if ((error = xfs_qm_sync(mp, flags))) {
/*
* If we got an IO error, we will be shutting down.
* So, there's nothing more for us to do here.
*/
ASSERT(error != EIO || XFS_FORCED_SHUTDOWN(mp));
if (XFS_FORCED_SHUTDOWN(mp)) {
return XFS_ERROR(error);
}
}
/*
* 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)
{
xfs_mount_t *mp = ip->i_mount;
xfs_dquot_t *dqp;
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);

View file

@ -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);

View file

@ -1,51 +0,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
*/
#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;
}

View file

@ -1,70 +0,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__ */

View file

@ -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);
}
/*

View file

@ -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)

View file

@ -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)

View file

@ -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 @@ out:
}
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 @@ out:
}
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;

View file

@ -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);

View file

@ -1,183 +0,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
*/
#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);
}

View file

@ -1,185 +0,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
*/
#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__ */

View file

@ -53,6 +53,7 @@
#include "xfs_trans_space.h"
#include "xfs_buf_item.h"
#include "xfs_filestream.h"
#include "xfs_vnodeops.h"
#ifdef DEBUG
@ -248,7 +249,7 @@ xfs_bmap_local_to_extents(
* Else, *lastxp will be set to the index of the found
* entry; *gotp will contain the entry.
*/
STATIC xfs_bmbt_rec_t * /* pointer to found extent entry */
STATIC xfs_bmbt_rec_host_t * /* pointer to found extent entry */
xfs_bmap_search_extents(
xfs_inode_t *ip, /* incore inode pointer */
xfs_fileoff_t bno, /* block number searched for */
@ -272,21 +273,6 @@ xfs_bmap_isaeof(
char *aeof); /* return value */
#ifdef XFS_BMAP_TRACE
/*
* Add a bmap trace buffer entry. Base routine for the others.
*/
STATIC void
xfs_bmap_trace_addentry(
int opcode, /* operation */
const char *fname, /* function name */
char *desc, /* operation description */
xfs_inode_t *ip, /* incore inode pointer */
xfs_extnum_t idx, /* index of entry(ies) */
xfs_extnum_t cnt, /* count of entries, 1 or 2 */
xfs_bmbt_rec_t *r1, /* first record */
xfs_bmbt_rec_t *r2, /* second record or null */
int whichfork); /* data or attr fork */
/*
* Add bmap trace entry prior to a call to xfs_iext_remove.
*/
@ -714,7 +700,7 @@ xfs_bmap_add_extent_delay_real(
{
xfs_btree_cur_t *cur; /* btree cursor */
int diff; /* temp value */
xfs_bmbt_rec_t *ep; /* extent entry for idx */
xfs_bmbt_rec_host_t *ep; /* extent entry for idx */
int error; /* error return value */
int i; /* temp state */
xfs_ifork_t *ifp; /* inode fork pointer */
@ -1270,7 +1256,7 @@ xfs_bmap_add_extent_unwritten_real(
xfs_extdelta_t *delta) /* Change made to incore extents */
{
xfs_btree_cur_t *cur; /* btree cursor */
xfs_bmbt_rec_t *ep; /* extent entry for idx */
xfs_bmbt_rec_host_t *ep; /* extent entry for idx */
int error; /* error return value */
int i; /* temp state */
xfs_ifork_t *ifp; /* inode fork pointer */
@ -1823,7 +1809,7 @@ xfs_bmap_add_extent_hole_delay(
xfs_extdelta_t *delta, /* Change made to incore extents */
int rsvd) /* OK to allocate reserved blocks */
{
xfs_bmbt_rec_t *ep; /* extent record for idx */
xfs_bmbt_rec_host_t *ep; /* extent record for idx */
xfs_ifork_t *ifp; /* inode fork pointer */
xfs_bmbt_irec_t left; /* left neighbor extent entry */
xfs_filblks_t newlen=0; /* new indirect size */
@ -2012,7 +1998,7 @@ xfs_bmap_add_extent_hole_real(
xfs_extdelta_t *delta, /* Change made to incore extents */
int whichfork) /* data or attr fork */
{
xfs_bmbt_rec_t *ep; /* pointer to extent entry ins. point */
xfs_bmbt_rec_host_t *ep; /* pointer to extent entry ins. point */
int error; /* error return value */
int i; /* temp state */
xfs_ifork_t *ifp; /* inode fork pointer */
@ -3070,7 +3056,7 @@ xfs_bmap_del_extent(
xfs_fileoff_t del_endoff; /* first offset past del */
int delay; /* current block is delayed allocated */
int do_fx; /* free extent at end of routine */
xfs_bmbt_rec_t *ep; /* current extent entry pointer */
xfs_bmbt_rec_host_t *ep; /* current extent entry pointer */
int error; /* error return value */
int flags; /* inode logging flags */
xfs_bmbt_irec_t got; /* current extent entry */
@ -3418,7 +3404,7 @@ xfs_bmap_extents_to_btree(
xfs_bmbt_rec_t *arp; /* child record pointer */
xfs_bmbt_block_t *block; /* btree root block */
xfs_btree_cur_t *cur; /* bmap btree cursor */
xfs_bmbt_rec_t *ep; /* extent record pointer */
xfs_bmbt_rec_host_t *ep; /* extent record pointer */
int error; /* error return value */
xfs_extnum_t i, cnt; /* extent record index */
xfs_ifork_t *ifp; /* inode fork pointer */
@ -3507,8 +3493,8 @@ xfs_bmap_extents_to_btree(
for (cnt = i = 0; i < nextents; i++) {
ep = xfs_iext_get_ext(ifp, i);
if (!ISNULLSTARTBLOCK(xfs_bmbt_get_startblock(ep))) {
arp->l0 = INT_GET(ep->l0, ARCH_CONVERT);
arp->l1 = INT_GET(ep->l1, ARCH_CONVERT);
arp->l0 = cpu_to_be64(ep->l0);
arp->l1 = cpu_to_be64(ep->l1);
arp++; cnt++;
}
}
@ -3590,7 +3576,7 @@ xfs_bmap_local_to_extents(
if (ifp->if_bytes) {
xfs_alloc_arg_t args; /* allocation arguments */
xfs_buf_t *bp; /* buffer for extent block */
xfs_bmbt_rec_t *ep; /* extent record pointer */
xfs_bmbt_rec_host_t *ep;/* extent record pointer */
args.tp = tp;
args.mp = ip->i_mount;
@ -3655,7 +3641,7 @@ done:
* entry (null if none). Else, *lastxp will be set to the index
* of the found entry; *gotp will contain the entry.
*/
xfs_bmbt_rec_t * /* pointer to found extent entry */
xfs_bmbt_rec_host_t * /* pointer to found extent entry */
xfs_bmap_search_multi_extents(
xfs_ifork_t *ifp, /* inode fork pointer */
xfs_fileoff_t bno, /* block number searched for */
@ -3664,7 +3650,7 @@ xfs_bmap_search_multi_extents(
xfs_bmbt_irec_t *gotp, /* out: extent entry found */
xfs_bmbt_irec_t *prevp) /* out: previous extent entry found */
{
xfs_bmbt_rec_t *ep; /* extent record pointer */
xfs_bmbt_rec_host_t *ep; /* extent record pointer */
xfs_extnum_t lastx; /* last extent index */
/*
@ -3706,7 +3692,7 @@ xfs_bmap_search_multi_extents(
* Else, *lastxp will be set to the index of the found
* entry; *gotp will contain the entry.
*/
STATIC xfs_bmbt_rec_t * /* pointer to found extent entry */
STATIC xfs_bmbt_rec_host_t * /* pointer to found extent entry */
xfs_bmap_search_extents(
xfs_inode_t *ip, /* incore inode pointer */
xfs_fileoff_t bno, /* block number searched for */
@ -3717,7 +3703,7 @@ xfs_bmap_search_extents(
xfs_bmbt_irec_t *prevp) /* out: previous extent entry found */
{
xfs_ifork_t *ifp; /* inode fork pointer */
xfs_bmbt_rec_t *ep; /* extent record pointer */
xfs_bmbt_rec_host_t *ep; /* extent record pointer */
XFS_STATS_INC(xs_look_exlist);
ifp = XFS_IFORK_PTR(ip, fork);
@ -3757,11 +3743,11 @@ xfs_bmap_trace_addentry(
xfs_inode_t *ip, /* incore inode pointer */
xfs_extnum_t idx, /* index of entry(ies) */
xfs_extnum_t cnt, /* count of entries, 1 or 2 */
xfs_bmbt_rec_t *r1, /* first record */
xfs_bmbt_rec_t *r2, /* second record or null */
xfs_bmbt_rec_host_t *r1, /* first record */
xfs_bmbt_rec_host_t *r2, /* second record or null */
int whichfork) /* data or attr fork */
{
xfs_bmbt_rec_t tr2;
xfs_bmbt_rec_host_t tr2;
ASSERT(cnt == 1 || cnt == 2);
ASSERT(r1 != NULL);
@ -3842,8 +3828,8 @@ xfs_bmap_trace_insert(
xfs_bmbt_irec_t *r2, /* inserted record 2 or null */
int whichfork) /* data or attr fork */
{
xfs_bmbt_rec_t tr1; /* compressed record 1 */
xfs_bmbt_rec_t tr2; /* compressed record 2 if needed */
xfs_bmbt_rec_host_t tr1; /* compressed record 1 */
xfs_bmbt_rec_host_t tr2; /* compressed record 2 if needed */
xfs_bmbt_set_all(&tr1, r1);
if (cnt == 2) {
@ -4316,7 +4302,6 @@ xfs_bmap_first_unused(
xfs_fileoff_t *first_unused, /* unused block */
int whichfork) /* data or attr fork */
{
xfs_bmbt_rec_t *ep; /* pointer to an extent entry */
int error; /* error return value */
int idx; /* extent record index */
xfs_ifork_t *ifp; /* inode fork pointer */
@ -4340,7 +4325,7 @@ xfs_bmap_first_unused(
lowest = *first_unused;
nextents = ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t);
for (idx = 0, lastaddr = 0, max = lowest; idx < nextents; idx++) {
ep = xfs_iext_get_ext(ifp, idx);
xfs_bmbt_rec_host_t *ep = xfs_iext_get_ext(ifp, idx);
off = xfs_bmbt_get_startoff(ep);
/*
* See if the hole before this extent will work.
@ -4371,7 +4356,7 @@ xfs_bmap_last_before(
{
xfs_fileoff_t bno; /* input file offset */
int eof; /* hit end of file */
xfs_bmbt_rec_t *ep; /* pointer to last extent */
xfs_bmbt_rec_host_t *ep; /* pointer to last extent */
int error; /* error return value */
xfs_bmbt_irec_t got; /* current extent value */
xfs_ifork_t *ifp; /* inode fork pointer */
@ -4417,7 +4402,7 @@ xfs_bmap_last_offset(
xfs_fileoff_t *last_block, /* last block */
int whichfork) /* data or attr fork */
{
xfs_bmbt_rec_t *ep; /* pointer to last extent */
xfs_bmbt_rec_host_t *ep; /* pointer to last extent */
int error; /* error return value */
xfs_ifork_t *ifp; /* inode fork pointer */
xfs_extnum_t nextents; /* number of extent entries */
@ -4454,7 +4439,7 @@ xfs_bmap_one_block(
xfs_inode_t *ip, /* incore inode */
int whichfork) /* data or attr fork */
{
xfs_bmbt_rec_t *ep; /* ptr to fork's extent */
xfs_bmbt_rec_host_t *ep; /* ptr to fork's extent */
xfs_ifork_t *ifp; /* inode fork pointer */
int rval; /* return value */
xfs_bmbt_irec_t s; /* internal version of extent */
@ -4549,7 +4534,7 @@ xfs_bmap_read_extents(
* Loop over all leaf nodes. Copy information to the extent records.
*/
for (;;) {
xfs_bmbt_rec_t *frp, *trp;
xfs_bmbt_rec_t *frp;
xfs_fsblock_t nextbno;
xfs_extnum_t num_recs;
xfs_extnum_t start;
@ -4581,9 +4566,9 @@ xfs_bmap_read_extents(
frp = XFS_BTREE_REC_ADDR(xfs_bmbt, block, 1);
start = i;
for (j = 0; j < num_recs; j++, i++, frp++) {
trp = xfs_iext_get_ext(ifp, i);
trp->l0 = INT_GET(frp->l0, ARCH_CONVERT);
trp->l1 = INT_GET(frp->l1, ARCH_CONVERT);
xfs_bmbt_rec_host_t *trp = xfs_iext_get_ext(ifp, i);
trp->l0 = be64_to_cpu(frp->l0);
trp->l1 = be64_to_cpu(frp->l1);
}
if (exntf == XFS_EXTFMT_NOSTATE) {
/*
@ -4631,7 +4616,7 @@ xfs_bmap_trace_exlist(
xfs_extnum_t cnt, /* count of entries in the list */
int whichfork) /* data or attr fork */
{
xfs_bmbt_rec_t *ep; /* current extent record */
xfs_bmbt_rec_host_t *ep; /* current extent record */
xfs_extnum_t idx; /* extent record index */
xfs_ifork_t *ifp; /* inode fork pointer */
xfs_bmbt_irec_t s; /* file extent record */
@ -4727,7 +4712,7 @@ xfs_bmapi(
xfs_btree_cur_t *cur; /* bmap btree cursor */
xfs_fileoff_t end; /* end of mapped file region */
int eof; /* we've hit the end of extents */
xfs_bmbt_rec_t *ep; /* extent record pointer */
xfs_bmbt_rec_host_t *ep; /* extent record pointer */
int error; /* error return */
xfs_bmbt_irec_t got; /* current file extent record */
xfs_ifork_t *ifp; /* inode fork pointer */
@ -5378,7 +5363,7 @@ xfs_bunmapi(
xfs_btree_cur_t *cur; /* bmap btree cursor */
xfs_bmbt_irec_t del; /* extent being deleted */
int eof; /* is deleting at eof */
xfs_bmbt_rec_t *ep; /* extent record pointer */
xfs_bmbt_rec_host_t *ep; /* extent record pointer */
int error; /* error return value */
xfs_extnum_t extno; /* extent number in list */
xfs_bmbt_irec_t got; /* current extent record */
@ -5742,12 +5727,45 @@ error0:
return error;
}
/*
* returns 1 for success, 0 if we failed to map the extent.
*/
STATIC int
xfs_getbmapx_fix_eof_hole(
xfs_inode_t *ip, /* xfs incore inode pointer */
struct getbmap *out, /* output structure */
int prealloced, /* this is a file with
* preallocated data space */
__int64_t end, /* last block requested */
xfs_fsblock_t startblock)
{
__int64_t fixlen;
xfs_mount_t *mp; /* file system mount point */
if (startblock == HOLESTARTBLOCK) {
mp = ip->i_mount;
out->bmv_block = -1;
fixlen = XFS_FSB_TO_BB(mp, XFS_B_TO_FSB(mp, ip->i_size));
fixlen -= out->bmv_offset;
if (prealloced && out->bmv_offset + out->bmv_length == end) {
/* Came to hole at EOF. Trim it. */
if (fixlen <= 0)
return 0;
out->bmv_length = fixlen;
}
} else {
out->bmv_block = XFS_FSB_TO_DB(ip, startblock);
}
return 1;
}
/*
* Fcntl interface to xfs_bmapi.
*/
int /* error code */
xfs_getbmap(
bhv_desc_t *bdp, /* XFS behavior descriptor*/
xfs_inode_t *ip,
struct getbmap *bmv, /* user bmap structure */
void __user *ap, /* pointer to user's array */
int interface) /* interface flags */
@ -5756,7 +5774,6 @@ xfs_getbmap(
int error; /* return value */
__int64_t fixlen; /* length for -1 case */
int i; /* extent number */
xfs_inode_t *ip; /* xfs incore inode pointer */
bhv_vnode_t *vp; /* corresponding vnode */
int lock; /* lock state */
xfs_bmbt_irec_t *map; /* buffer for user's data */
@ -5774,8 +5791,7 @@ xfs_getbmap(
int bmapi_flags; /* flags for xfs_bmapi */
__int32_t oflags; /* getbmapx bmv_oflags field */
vp = BHV_TO_VNODE(bdp);
ip = XFS_BHVTOI(bdp);
vp = XFS_ITOV(ip);
mp = ip->i_mount;
whichfork = interface & BMV_IF_ATTRFORK ? XFS_ATTR_FORK : XFS_DATA_FORK;
@ -5794,10 +5810,9 @@ xfs_getbmap(
* could misinterpret holes in a DMAPI file as true holes,
* when in fact they may represent offline user data.
*/
if ( (interface & BMV_IF_NO_DMAPI_READ) == 0
&& DM_EVENT_ENABLED(vp->v_vfsp, ip, DM_EVENT_READ)
&& whichfork == XFS_DATA_FORK) {
if ((interface & BMV_IF_NO_DMAPI_READ) == 0 &&
DM_EVENT_ENABLED(ip, DM_EVENT_READ) &&
whichfork == XFS_DATA_FORK) {
error = XFS_SEND_DATA(mp, DM_EVENT_READ, vp, 0, 0, 0, NULL);
if (error)
return XFS_ERROR(error);
@ -5854,7 +5869,8 @@ xfs_getbmap(
if (whichfork == XFS_DATA_FORK &&
(ip->i_delayed_blks || ip->i_size > ip->i_d.di_size)) {
/* xfs_fsize_t last_byte = xfs_file_last_byte(ip); */
error = bhv_vop_flush_pages(vp, (xfs_off_t)0, -1, 0, FI_REMAPF);
error = xfs_flush_pages(ip, (xfs_off_t)0,
-1, 0, FI_REMAPF);
}
ASSERT(whichfork == XFS_ATTR_FORK || ip->i_delayed_blks == 0);
@ -5904,18 +5920,15 @@ xfs_getbmap(
out.bmv_length = XFS_FSB_TO_BB(mp, map[i].br_blockcount);
ASSERT(map[i].br_startblock != DELAYSTARTBLOCK);
if (map[i].br_startblock == HOLESTARTBLOCK &&
((prealloced && out.bmv_offset + out.bmv_length == bmvend) ||
whichfork == XFS_ATTR_FORK )) {
/*
* came to hole at end of file or the end of
attribute fork
*/
whichfork == XFS_ATTR_FORK) {
/* came to the end of attribute fork */
goto unlock_and_return;
} else {
out.bmv_block =
(map[i].br_startblock == HOLESTARTBLOCK) ?
-1 :
XFS_FSB_TO_DB(ip, map[i].br_startblock);
if (!xfs_getbmapx_fix_eof_hole(ip, &out,
prealloced, bmvend,
map[i].br_startblock)) {
goto unlock_and_return;
}
/* return either getbmap/getbmapx structure. */
if (interface & BMV_IF_EXTENDED) {
@ -5974,7 +5987,7 @@ xfs_bmap_isaeof(
{
int error; /* error return value */
xfs_ifork_t *ifp; /* inode fork pointer */
xfs_bmbt_rec_t *lastrec; /* extent record pointer */
xfs_bmbt_rec_host_t *lastrec; /* extent record pointer */
xfs_extnum_t nextents; /* number of file extents */
xfs_bmbt_irec_t s; /* expanded extent record */
@ -6018,7 +6031,7 @@ xfs_bmap_eof(
xfs_fsblock_t blockcount; /* extent block count */
int error; /* error return value */
xfs_ifork_t *ifp; /* inode fork pointer */
xfs_bmbt_rec_t *lastrec; /* extent record pointer */
xfs_bmbt_rec_host_t *lastrec; /* extent record pointer */
xfs_extnum_t nextents; /* number of file extents */
xfs_fileoff_t startoff; /* extent starting file offset */
@ -6465,10 +6478,9 @@ xfs_bmap_count_leaves(
int *count)
{
int b;
xfs_bmbt_rec_t *frp;
for (b = 0; b < numrecs; b++) {
frp = xfs_iext_get_ext(ifp, idx + b);
xfs_bmbt_rec_host_t *frp = xfs_iext_get_ext(ifp, idx + b);
*count += xfs_bmbt_get_blockcount(frp);
}
return 0;

View file

@ -335,7 +335,7 @@ xfs_bunmapi(
*/
int /* error code */
xfs_getbmap(
bhv_desc_t *bdp, /* XFS behavior descriptor*/
xfs_inode_t *ip,
struct getbmap *bmv, /* user bmap structure */
void __user *ap, /* pointer to user's array */
int iflags); /* interface flags */
@ -378,7 +378,7 @@ xfs_check_nostate_extents(
* entry (null if none). Else, *lastxp will be set to the index
* of the found entry; *gotp will contain the entry.
*/
xfs_bmbt_rec_t *
xfs_bmbt_rec_host_t *
xfs_bmap_search_multi_extents(struct xfs_ifork *, xfs_fileoff_t, int *,
xfs_extnum_t *, xfs_bmbt_irec_t *, xfs_bmbt_irec_t *);

View file

@ -260,13 +260,14 @@ xfs_bmbt_trace_cursor(
char *s,
int line)
{
xfs_bmbt_rec_t r;
xfs_bmbt_rec_host_t r;
xfs_bmbt_set_all(&r, &cur->bc_rec.b);
xfs_bmbt_trace_enter(func, cur, s, XFS_BMBT_KTRACE_CUR, line,
(cur->bc_nlevels << 24) | (cur->bc_private.b.flags << 16) |
cur->bc_private.b.allocated,
INT_GET(r.l0, ARCH_CONVERT) >> 32, (int)INT_GET(r.l0, ARCH_CONVERT), INT_GET(r.l1, ARCH_CONVERT) >> 32, (int)INT_GET(r.l1, ARCH_CONVERT),
r.l0 >> 32, (int)r.l0,
r.l1 >> 32, (int)r.l1,
(unsigned long)cur->bc_bufs[0], (unsigned long)cur->bc_bufs[1],
(unsigned long)cur->bc_bufs[2], (unsigned long)cur->bc_bufs[3],
(cur->bc_ptrs[0] << 16) | cur->bc_ptrs[1],
@ -383,7 +384,7 @@ xfs_bmbt_delrec(
if (ptr < numrecs) {
memmove(&kp[ptr - 1], &kp[ptr],
(numrecs - ptr) * sizeof(*kp));
memmove(&pp[ptr - 1], &pp[ptr], /* INT_: direct copy */
memmove(&pp[ptr - 1], &pp[ptr],
(numrecs - ptr) * sizeof(*pp));
xfs_bmbt_log_ptrs(cur, bp, ptr, numrecs - 1);
xfs_bmbt_log_keys(cur, bp, ptr, numrecs - 1);
@ -815,7 +816,7 @@ xfs_bmbt_insrec(
#endif
memmove(&kp[ptr], &kp[ptr - 1],
(numrecs - ptr + 1) * sizeof(*kp));
memmove(&pp[ptr], &pp[ptr - 1], /* INT_: direct copy */
memmove(&pp[ptr], &pp[ptr - 1],
(numrecs - ptr + 1) * sizeof(*pp));
#ifdef DEBUG
if ((error = xfs_btree_check_lptr(cur, *bnop, level))) {
@ -1250,7 +1251,7 @@ xfs_bmbt_lshift(
return error;
}
#endif
*lpp = *rpp; /* INT_: direct copy */
*lpp = *rpp;
xfs_bmbt_log_ptrs(cur, lbp, lrecs, lrecs);
} else {
lrp = XFS_BMAP_REC_IADDR(left, lrecs, cur);
@ -1388,7 +1389,7 @@ xfs_bmbt_rshift(
}
#endif
*rkp = *lkp;
*rpp = *lpp; /* INT_: direct copy */
*rpp = *lpp;
xfs_bmbt_log_keys(cur, rbp, 1, be16_to_cpu(right->bb_numrecs) + 1);
xfs_bmbt_log_ptrs(cur, rbp, 1, be16_to_cpu(right->bb_numrecs) + 1);
} else {
@ -1826,7 +1827,7 @@ __xfs_bmbt_get_all(
void
xfs_bmbt_get_all(
xfs_bmbt_rec_t *r,
xfs_bmbt_rec_host_t *r,
xfs_bmbt_irec_t *s)
{
__xfs_bmbt_get_all(r->l0, r->l1, s);
@ -1862,7 +1863,7 @@ xfs_bmbt_get_block(
*/
xfs_filblks_t
xfs_bmbt_get_blockcount(
xfs_bmbt_rec_t *r)
xfs_bmbt_rec_host_t *r)
{
return (xfs_filblks_t)(r->l1 & XFS_MASK64LO(21));
}
@ -1872,7 +1873,7 @@ xfs_bmbt_get_blockcount(
*/
xfs_fsblock_t
xfs_bmbt_get_startblock(
xfs_bmbt_rec_t *r)
xfs_bmbt_rec_host_t *r)
{
#if XFS_BIG_BLKNOS
return (((xfs_fsblock_t)r->l0 & XFS_MASK64LO(9)) << 43) |
@ -1896,7 +1897,7 @@ xfs_bmbt_get_startblock(
*/
xfs_fileoff_t
xfs_bmbt_get_startoff(
xfs_bmbt_rec_t *r)
xfs_bmbt_rec_host_t *r)
{
return ((xfs_fileoff_t)r->l0 &
XFS_MASK64LO(64 - BMBT_EXNTFLAG_BITLEN)) >> 9;
@ -1904,7 +1905,7 @@ xfs_bmbt_get_startoff(
xfs_exntst_t
xfs_bmbt_get_state(
xfs_bmbt_rec_t *r)
xfs_bmbt_rec_host_t *r)
{
int ext_flag;
@ -1913,19 +1914,13 @@ xfs_bmbt_get_state(
ext_flag);
}
#ifndef XFS_NATIVE_HOST
/* Endian flipping versions of the bmbt extraction functions */
void
xfs_bmbt_disk_get_all(
xfs_bmbt_rec_t *r,
xfs_bmbt_irec_t *s)
{
__uint64_t l0, l1;
l0 = INT_GET(r->l0, ARCH_CONVERT);
l1 = INT_GET(r->l1, ARCH_CONVERT);
__xfs_bmbt_get_all(l0, l1, s);
__xfs_bmbt_get_all(be64_to_cpu(r->l0), be64_to_cpu(r->l1), s);
}
/*
@ -1935,7 +1930,7 @@ xfs_filblks_t
xfs_bmbt_disk_get_blockcount(
xfs_bmbt_rec_t *r)
{
return (xfs_filblks_t)(INT_GET(r->l1, ARCH_CONVERT) & XFS_MASK64LO(21));
return (xfs_filblks_t)(be64_to_cpu(r->l1) & XFS_MASK64LO(21));
}
/*
@ -1945,11 +1940,9 @@ xfs_fileoff_t
xfs_bmbt_disk_get_startoff(
xfs_bmbt_rec_t *r)
{
return ((xfs_fileoff_t)INT_GET(r->l0, ARCH_CONVERT) &
return ((xfs_fileoff_t)be64_to_cpu(r->l0) &
XFS_MASK64LO(64 - BMBT_EXNTFLAG_BITLEN)) >> 9;
}
#endif /* XFS_NATIVE_HOST */
/*
* Increment cursor by one record at the level.
@ -2289,93 +2282,114 @@ xfs_bmbt_newroot(
return 0;
}
/*
* Set all the fields in a bmap extent record from the uncompressed form.
*/
void
xfs_bmbt_set_all(
xfs_bmbt_rec_t *r,
xfs_bmbt_irec_t *s)
{
int extent_flag;
ASSERT((s->br_state == XFS_EXT_NORM) ||
(s->br_state == XFS_EXT_UNWRITTEN));
extent_flag = (s->br_state == XFS_EXT_NORM) ? 0 : 1;
ASSERT((s->br_startoff & XFS_MASK64HI(9)) == 0);
ASSERT((s->br_blockcount & XFS_MASK64HI(43)) == 0);
#if XFS_BIG_BLKNOS
ASSERT((s->br_startblock & XFS_MASK64HI(12)) == 0);
r->l0 = ((xfs_bmbt_rec_base_t)extent_flag << 63) |
((xfs_bmbt_rec_base_t)s->br_startoff << 9) |
((xfs_bmbt_rec_base_t)s->br_startblock >> 43);
r->l1 = ((xfs_bmbt_rec_base_t)s->br_startblock << 21) |
((xfs_bmbt_rec_base_t)s->br_blockcount &
(xfs_bmbt_rec_base_t)XFS_MASK64LO(21));
#else /* !XFS_BIG_BLKNOS */
if (ISNULLSTARTBLOCK(s->br_startblock)) {
r->l0 = ((xfs_bmbt_rec_base_t)extent_flag << 63) |
((xfs_bmbt_rec_base_t)s->br_startoff << 9) |
(xfs_bmbt_rec_base_t)XFS_MASK64LO(9);
r->l1 = XFS_MASK64HI(11) |
((xfs_bmbt_rec_base_t)s->br_startblock << 21) |
((xfs_bmbt_rec_base_t)s->br_blockcount &
(xfs_bmbt_rec_base_t)XFS_MASK64LO(21));
} else {
r->l0 = ((xfs_bmbt_rec_base_t)extent_flag << 63) |
((xfs_bmbt_rec_base_t)s->br_startoff << 9);
r->l1 = ((xfs_bmbt_rec_base_t)s->br_startblock << 21) |
((xfs_bmbt_rec_base_t)s->br_blockcount &
(xfs_bmbt_rec_base_t)XFS_MASK64LO(21));
}
#endif /* XFS_BIG_BLKNOS */
}
/*
* Set all the fields in a bmap extent record from the arguments.
*/
void
xfs_bmbt_set_allf(
xfs_bmbt_rec_t *r,
xfs_fileoff_t o,
xfs_fsblock_t b,
xfs_filblks_t c,
xfs_exntst_t v)
xfs_bmbt_rec_host_t *r,
xfs_fileoff_t startoff,
xfs_fsblock_t startblock,
xfs_filblks_t blockcount,
xfs_exntst_t state)
{
int extent_flag;
int extent_flag = (state == XFS_EXT_NORM) ? 0 : 1;
ASSERT(state == XFS_EXT_NORM || state == XFS_EXT_UNWRITTEN);
ASSERT((startoff & XFS_MASK64HI(64-BMBT_STARTOFF_BITLEN)) == 0);
ASSERT((blockcount & XFS_MASK64HI(64-BMBT_BLOCKCOUNT_BITLEN)) == 0);
ASSERT((v == XFS_EXT_NORM) || (v == XFS_EXT_UNWRITTEN));
extent_flag = (v == XFS_EXT_NORM) ? 0 : 1;
ASSERT((o & XFS_MASK64HI(64-BMBT_STARTOFF_BITLEN)) == 0);
ASSERT((c & XFS_MASK64HI(64-BMBT_BLOCKCOUNT_BITLEN)) == 0);
#if XFS_BIG_BLKNOS
ASSERT((b & XFS_MASK64HI(64-BMBT_STARTBLOCK_BITLEN)) == 0);
ASSERT((startblock & XFS_MASK64HI(64-BMBT_STARTBLOCK_BITLEN)) == 0);
r->l0 = ((xfs_bmbt_rec_base_t)extent_flag << 63) |
((xfs_bmbt_rec_base_t)o << 9) |
((xfs_bmbt_rec_base_t)b >> 43);
r->l1 = ((xfs_bmbt_rec_base_t)b << 21) |
((xfs_bmbt_rec_base_t)c &
((xfs_bmbt_rec_base_t)startoff << 9) |
((xfs_bmbt_rec_base_t)startblock >> 43);
r->l1 = ((xfs_bmbt_rec_base_t)startblock << 21) |
((xfs_bmbt_rec_base_t)blockcount &
(xfs_bmbt_rec_base_t)XFS_MASK64LO(21));
#else /* !XFS_BIG_BLKNOS */
if (ISNULLSTARTBLOCK(b)) {
if (ISNULLSTARTBLOCK(startblock)) {
r->l0 = ((xfs_bmbt_rec_base_t)extent_flag << 63) |
((xfs_bmbt_rec_base_t)o << 9) |
((xfs_bmbt_rec_base_t)startoff << 9) |
(xfs_bmbt_rec_base_t)XFS_MASK64LO(9);
r->l1 = XFS_MASK64HI(11) |
((xfs_bmbt_rec_base_t)b << 21) |
((xfs_bmbt_rec_base_t)c &
((xfs_bmbt_rec_base_t)startblock << 21) |
((xfs_bmbt_rec_base_t)blockcount &
(xfs_bmbt_rec_base_t)XFS_MASK64LO(21));
} else {
r->l0 = ((xfs_bmbt_rec_base_t)extent_flag << 63) |
((xfs_bmbt_rec_base_t)o << 9);
r->l1 = ((xfs_bmbt_rec_base_t)b << 21) |
((xfs_bmbt_rec_base_t)c &
((xfs_bmbt_rec_base_t)startoff << 9);
r->l1 = ((xfs_bmbt_rec_base_t)startblock << 21) |
((xfs_bmbt_rec_base_t)blockcount &
(xfs_bmbt_rec_base_t)XFS_MASK64LO(21));
}
#endif /* XFS_BIG_BLKNOS */
}
#ifndef XFS_NATIVE_HOST
/*
* Set all the fields in a bmap extent record from the uncompressed form.
*/
void
xfs_bmbt_set_all(
xfs_bmbt_rec_host_t *r,
xfs_bmbt_irec_t *s)
{
xfs_bmbt_set_allf(r, s->br_startoff, s->br_startblock,
s->br_blockcount, s->br_state);
}
/*
* Set all the fields in a disk format bmap extent record from the arguments.
*/
void
xfs_bmbt_disk_set_allf(
xfs_bmbt_rec_t *r,
xfs_fileoff_t startoff,
xfs_fsblock_t startblock,
xfs_filblks_t blockcount,
xfs_exntst_t state)
{
int extent_flag = (state == XFS_EXT_NORM) ? 0 : 1;
ASSERT(state == XFS_EXT_NORM || state == XFS_EXT_UNWRITTEN);
ASSERT((startoff & XFS_MASK64HI(64-BMBT_STARTOFF_BITLEN)) == 0);
ASSERT((blockcount & XFS_MASK64HI(64-BMBT_BLOCKCOUNT_BITLEN)) == 0);
#if XFS_BIG_BLKNOS
ASSERT((startblock & XFS_MASK64HI(64-BMBT_STARTBLOCK_BITLEN)) == 0);
r->l0 = cpu_to_be64(
((xfs_bmbt_rec_base_t)extent_flag << 63) |
((xfs_bmbt_rec_base_t)startoff << 9) |
((xfs_bmbt_rec_base_t)startblock >> 43));
r->l1 = cpu_to_be64(
((xfs_bmbt_rec_base_t)startblock << 21) |
((xfs_bmbt_rec_base_t)blockcount &
(xfs_bmbt_rec_base_t)XFS_MASK64LO(21)));
#else /* !XFS_BIG_BLKNOS */
if (ISNULLSTARTBLOCK(startblock)) {
r->l0 = cpu_to_be64(
((xfs_bmbt_rec_base_t)extent_flag << 63) |
((xfs_bmbt_rec_base_t)startoff << 9) |
(xfs_bmbt_rec_base_t)XFS_MASK64LO(9));
r->l1 = cpu_to_be64(XFS_MASK64HI(11) |
((xfs_bmbt_rec_base_t)startblock << 21) |
((xfs_bmbt_rec_base_t)blockcount &
(xfs_bmbt_rec_base_t)XFS_MASK64LO(21)));
} else {
r->l0 = cpu_to_be64(
((xfs_bmbt_rec_base_t)extent_flag << 63) |
((xfs_bmbt_rec_base_t)startoff << 9));
r->l1 = cpu_to_be64(
((xfs_bmbt_rec_base_t)startblock << 21) |
((xfs_bmbt_rec_base_t)blockcount &
(xfs_bmbt_rec_base_t)XFS_MASK64LO(21)));
}
#endif /* XFS_BIG_BLKNOS */
}
/*
* Set all the fields in a bmap extent record from the uncompressed form.
*/
@ -2384,91 +2398,16 @@ xfs_bmbt_disk_set_all(
xfs_bmbt_rec_t *r,
xfs_bmbt_irec_t *s)
{
int extent_flag;
ASSERT((s->br_state == XFS_EXT_NORM) ||
(s->br_state == XFS_EXT_UNWRITTEN));
extent_flag = (s->br_state == XFS_EXT_NORM) ? 0 : 1;
ASSERT((s->br_startoff & XFS_MASK64HI(9)) == 0);
ASSERT((s->br_blockcount & XFS_MASK64HI(43)) == 0);
#if XFS_BIG_BLKNOS
ASSERT((s->br_startblock & XFS_MASK64HI(12)) == 0);
INT_SET(r->l0, ARCH_CONVERT, ((xfs_bmbt_rec_base_t)extent_flag << 63) |
((xfs_bmbt_rec_base_t)s->br_startoff << 9) |
((xfs_bmbt_rec_base_t)s->br_startblock >> 43));
INT_SET(r->l1, ARCH_CONVERT, ((xfs_bmbt_rec_base_t)s->br_startblock << 21) |
((xfs_bmbt_rec_base_t)s->br_blockcount &
(xfs_bmbt_rec_base_t)XFS_MASK64LO(21)));
#else /* !XFS_BIG_BLKNOS */
if (ISNULLSTARTBLOCK(s->br_startblock)) {
INT_SET(r->l0, ARCH_CONVERT, ((xfs_bmbt_rec_base_t)extent_flag << 63) |
((xfs_bmbt_rec_base_t)s->br_startoff << 9) |
(xfs_bmbt_rec_base_t)XFS_MASK64LO(9));
INT_SET(r->l1, ARCH_CONVERT, XFS_MASK64HI(11) |
((xfs_bmbt_rec_base_t)s->br_startblock << 21) |
((xfs_bmbt_rec_base_t)s->br_blockcount &
(xfs_bmbt_rec_base_t)XFS_MASK64LO(21)));
} else {
INT_SET(r->l0, ARCH_CONVERT, ((xfs_bmbt_rec_base_t)extent_flag << 63) |
((xfs_bmbt_rec_base_t)s->br_startoff << 9));
INT_SET(r->l1, ARCH_CONVERT, ((xfs_bmbt_rec_base_t)s->br_startblock << 21) |
((xfs_bmbt_rec_base_t)s->br_blockcount &
(xfs_bmbt_rec_base_t)XFS_MASK64LO(21)));
}
#endif /* XFS_BIG_BLKNOS */
xfs_bmbt_disk_set_allf(r, s->br_startoff, s->br_startblock,
s->br_blockcount, s->br_state);
}
/*
* Set all the fields in a disk format bmap extent record from the arguments.
*/
void
xfs_bmbt_disk_set_allf(
xfs_bmbt_rec_t *r,
xfs_fileoff_t o,
xfs_fsblock_t b,
xfs_filblks_t c,
xfs_exntst_t v)
{
int extent_flag;
ASSERT((v == XFS_EXT_NORM) || (v == XFS_EXT_UNWRITTEN));
extent_flag = (v == XFS_EXT_NORM) ? 0 : 1;
ASSERT((o & XFS_MASK64HI(64-BMBT_STARTOFF_BITLEN)) == 0);
ASSERT((c & XFS_MASK64HI(64-BMBT_BLOCKCOUNT_BITLEN)) == 0);
#if XFS_BIG_BLKNOS
ASSERT((b & XFS_MASK64HI(64-BMBT_STARTBLOCK_BITLEN)) == 0);
INT_SET(r->l0, ARCH_CONVERT, ((xfs_bmbt_rec_base_t)extent_flag << 63) |
((xfs_bmbt_rec_base_t)o << 9) |
((xfs_bmbt_rec_base_t)b >> 43));
INT_SET(r->l1, ARCH_CONVERT, ((xfs_bmbt_rec_base_t)b << 21) |
((xfs_bmbt_rec_base_t)c &
(xfs_bmbt_rec_base_t)XFS_MASK64LO(21)));
#else /* !XFS_BIG_BLKNOS */
if (ISNULLSTARTBLOCK(b)) {
INT_SET(r->l0, ARCH_CONVERT, ((xfs_bmbt_rec_base_t)extent_flag << 63) |
((xfs_bmbt_rec_base_t)o << 9) |
(xfs_bmbt_rec_base_t)XFS_MASK64LO(9));
INT_SET(r->l1, ARCH_CONVERT, XFS_MASK64HI(11) |
((xfs_bmbt_rec_base_t)b << 21) |
((xfs_bmbt_rec_base_t)c &
(xfs_bmbt_rec_base_t)XFS_MASK64LO(21)));
} else {
INT_SET(r->l0, ARCH_CONVERT, ((xfs_bmbt_rec_base_t)extent_flag << 63) |
((xfs_bmbt_rec_base_t)o << 9));
INT_SET(r->l1, ARCH_CONVERT, ((xfs_bmbt_rec_base_t)b << 21) |
((xfs_bmbt_rec_base_t)c &
(xfs_bmbt_rec_base_t)XFS_MASK64LO(21)));
}
#endif /* XFS_BIG_BLKNOS */
}
#endif /* XFS_NATIVE_HOST */
/*
* Set the blockcount field in a bmap extent record.
*/
void
xfs_bmbt_set_blockcount(
xfs_bmbt_rec_t *r,
xfs_bmbt_rec_host_t *r,
xfs_filblks_t v)
{
ASSERT((v & XFS_MASK64HI(43)) == 0);
@ -2481,7 +2420,7 @@ xfs_bmbt_set_blockcount(
*/
void
xfs_bmbt_set_startblock(
xfs_bmbt_rec_t *r,
xfs_bmbt_rec_host_t *r,
xfs_fsblock_t v)
{
#if XFS_BIG_BLKNOS
@ -2509,7 +2448,7 @@ xfs_bmbt_set_startblock(
*/
void
xfs_bmbt_set_startoff(
xfs_bmbt_rec_t *r,
xfs_bmbt_rec_host_t *r,
xfs_fileoff_t v)
{
ASSERT((v & XFS_MASK64HI(9)) == 0);
@ -2523,7 +2462,7 @@ xfs_bmbt_set_startoff(
*/
void
xfs_bmbt_set_state(
xfs_bmbt_rec_t *r,
xfs_bmbt_rec_host_t *r,
xfs_exntst_t v)
{
ASSERT(v == XFS_EXT_NORM || v == XFS_EXT_UNWRITTEN);
@ -2624,10 +2563,8 @@ xfs_check_nostate_extents(
xfs_extnum_t idx,
xfs_extnum_t num)
{
xfs_bmbt_rec_t *ep;
for (; num > 0; num--, idx++) {
ep = xfs_iext_get_ext(ifp, idx);
xfs_bmbt_rec_host_t *ep = xfs_iext_get_ext(ifp, idx);
if ((ep->l0 >>
(64 - BMBT_EXNTFLAG_BITLEN)) != 0) {
ASSERT(0);

View file

@ -35,45 +35,16 @@ typedef struct xfs_bmdr_block {
/*
* Bmap btree record and extent descriptor.
* For 32-bit kernels,
* l0:31 is an extent flag (value 1 indicates non-normal).
* l0:0-30 and l1:9-31 are startoff.
* l1:0-8, l2:0-31, and l3:21-31 are startblock.
* l3:0-20 are blockcount.
* For 64-bit kernels,
* l0:63 is an extent flag (value 1 indicates non-normal).
* l0:9-62 are startoff.
* l0:0-8 and l1:21-63 are startblock.
* l1:0-20 are blockcount.
*/
#ifndef XFS_NATIVE_HOST
#define BMBT_TOTAL_BITLEN 128 /* 128 bits, 16 bytes */
#define BMBT_EXNTFLAG_BITOFF 0
#define BMBT_EXNTFLAG_BITLEN 1
#define BMBT_STARTOFF_BITOFF (BMBT_EXNTFLAG_BITOFF + BMBT_EXNTFLAG_BITLEN)
#define BMBT_STARTOFF_BITLEN 54
#define BMBT_STARTBLOCK_BITOFF (BMBT_STARTOFF_BITOFF + BMBT_STARTOFF_BITLEN)
#define BMBT_STARTBLOCK_BITLEN 52
#define BMBT_BLOCKCOUNT_BITOFF \
(BMBT_STARTBLOCK_BITOFF + BMBT_STARTBLOCK_BITLEN)
#define BMBT_BLOCKCOUNT_BITLEN (BMBT_TOTAL_BITLEN - BMBT_BLOCKCOUNT_BITOFF)
#else
#define BMBT_TOTAL_BITLEN 128 /* 128 bits, 16 bytes */
#define BMBT_EXNTFLAG_BITOFF 63
#define BMBT_EXNTFLAG_BITLEN 1
#define BMBT_STARTOFF_BITOFF (BMBT_EXNTFLAG_BITOFF - BMBT_STARTOFF_BITLEN)
#define BMBT_STARTOFF_BITLEN 54
#define BMBT_STARTBLOCK_BITOFF 85 /* 128 - 43 (other 9 is in first word) */
#define BMBT_STARTBLOCK_BITLEN 52
#define BMBT_BLOCKCOUNT_BITOFF 64 /* Start of second 64 bit container */
#define BMBT_BLOCKCOUNT_BITLEN 21
#endif /* XFS_NATIVE_HOST */
#define BMBT_USE_64 1
@ -83,12 +54,16 @@ typedef struct xfs_bmbt_rec_32
} xfs_bmbt_rec_32_t;
typedef struct xfs_bmbt_rec_64
{
__uint64_t l0, l1;
__be64 l0, l1;
} xfs_bmbt_rec_64_t;
typedef __uint64_t xfs_bmbt_rec_base_t; /* use this for casts */
typedef xfs_bmbt_rec_64_t xfs_bmbt_rec_t, xfs_bmdr_rec_t;
typedef struct xfs_bmbt_rec_host {
__uint64_t l0, l1;
} xfs_bmbt_rec_host_t;
/*
* Values and macros for delayed-allocation startblock fields.
*/
@ -281,23 +256,17 @@ extern ktrace_t *xfs_bmbt_trace_buf;
extern void xfs_bmdr_to_bmbt(xfs_bmdr_block_t *, int, xfs_bmbt_block_t *, int);
extern int xfs_bmbt_decrement(struct xfs_btree_cur *, int, int *);
extern int xfs_bmbt_delete(struct xfs_btree_cur *, int *);
extern void xfs_bmbt_get_all(xfs_bmbt_rec_t *r, xfs_bmbt_irec_t *s);
extern void xfs_bmbt_get_all(xfs_bmbt_rec_host_t *r, xfs_bmbt_irec_t *s);
extern xfs_bmbt_block_t *xfs_bmbt_get_block(struct xfs_btree_cur *cur,
int, struct xfs_buf **bpp);
extern xfs_filblks_t xfs_bmbt_get_blockcount(xfs_bmbt_rec_t *r);
extern xfs_fsblock_t xfs_bmbt_get_startblock(xfs_bmbt_rec_t *r);
extern xfs_fileoff_t xfs_bmbt_get_startoff(xfs_bmbt_rec_t *r);
extern xfs_exntst_t xfs_bmbt_get_state(xfs_bmbt_rec_t *r);
extern xfs_filblks_t xfs_bmbt_get_blockcount(xfs_bmbt_rec_host_t *r);
extern xfs_fsblock_t xfs_bmbt_get_startblock(xfs_bmbt_rec_host_t *r);
extern xfs_fileoff_t xfs_bmbt_get_startoff(xfs_bmbt_rec_host_t *r);
extern xfs_exntst_t xfs_bmbt_get_state(xfs_bmbt_rec_host_t *r);
#ifndef XFS_NATIVE_HOST
extern void xfs_bmbt_disk_get_all(xfs_bmbt_rec_t *r, xfs_bmbt_irec_t *s);
extern xfs_filblks_t xfs_bmbt_disk_get_blockcount(xfs_bmbt_rec_t *r);
extern xfs_fileoff_t xfs_bmbt_disk_get_startoff(xfs_bmbt_rec_t *r);
#else
#define xfs_bmbt_disk_get_all(r, s) xfs_bmbt_get_all(r, s)
#define xfs_bmbt_disk_get_blockcount(r) xfs_bmbt_get_blockcount(r)
#define xfs_bmbt_disk_get_startoff(r) xfs_bmbt_get_startoff(r)
#endif /* XFS_NATIVE_HOST */
extern int xfs_bmbt_increment(struct xfs_btree_cur *, int, int *);
extern int xfs_bmbt_insert(struct xfs_btree_cur *, int *);
@ -315,22 +284,17 @@ extern int xfs_bmbt_lookup_ge(struct xfs_btree_cur *, xfs_fileoff_t,
*/
extern int xfs_bmbt_newroot(struct xfs_btree_cur *cur, int *lflags, int *stat);
extern void xfs_bmbt_set_all(xfs_bmbt_rec_t *r, xfs_bmbt_irec_t *s);
extern void xfs_bmbt_set_allf(xfs_bmbt_rec_t *r, xfs_fileoff_t o,
extern void xfs_bmbt_set_all(xfs_bmbt_rec_host_t *r, xfs_bmbt_irec_t *s);
extern void xfs_bmbt_set_allf(xfs_bmbt_rec_host_t *r, xfs_fileoff_t o,
xfs_fsblock_t b, xfs_filblks_t c, xfs_exntst_t v);
extern void xfs_bmbt_set_blockcount(xfs_bmbt_rec_t *r, xfs_filblks_t v);
extern void xfs_bmbt_set_startblock(xfs_bmbt_rec_t *r, xfs_fsblock_t v);
extern void xfs_bmbt_set_startoff(xfs_bmbt_rec_t *r, xfs_fileoff_t v);
extern void xfs_bmbt_set_state(xfs_bmbt_rec_t *r, xfs_exntst_t v);
extern void xfs_bmbt_set_blockcount(xfs_bmbt_rec_host_t *r, xfs_filblks_t v);
extern void xfs_bmbt_set_startblock(xfs_bmbt_rec_host_t *r, xfs_fsblock_t v);
extern void xfs_bmbt_set_startoff(xfs_bmbt_rec_host_t *r, xfs_fileoff_t v);
extern void xfs_bmbt_set_state(xfs_bmbt_rec_host_t *r, xfs_exntst_t v);
#ifndef XFS_NATIVE_HOST
extern void xfs_bmbt_disk_set_all(xfs_bmbt_rec_t *r, xfs_bmbt_irec_t *s);
extern void xfs_bmbt_disk_set_allf(xfs_bmbt_rec_t *r, xfs_fileoff_t o,
xfs_fsblock_t b, xfs_filblks_t c, xfs_exntst_t v);
#else
#define xfs_bmbt_disk_set_all(r, s) xfs_bmbt_set_all(r, s)
#define xfs_bmbt_disk_set_allf(r, o, b, c, v) xfs_bmbt_set_allf(r, o, b, c, v)
#endif /* XFS_NATIVE_HOST */
extern void xfs_bmbt_to_bmdr(xfs_bmbt_block_t *, int, xfs_bmdr_block_t *, int);
extern int xfs_bmbt_update(struct xfs_btree_cur *, xfs_fileoff_t,

View file

@ -23,6 +23,7 @@
#include "xfs_inum.h"
#include "xfs_trans.h"
#include "xfs_sb.h"
#include "xfs_ag.h"
#include "xfs_dmapi.h"
#include "xfs_mount.h"
#include "xfs_buf_item.h"

View file

@ -89,7 +89,6 @@ struct xfs_mount_args {
#define XFSMNT_IDELETE 0x08000000 /* inode cluster delete */
#define XFSMNT_SWALLOC 0x10000000 /* turn on stripe width
* allocation */
#define XFSMNT_IHASHSIZE 0x20000000 /* inode hash table size */
#define XFSMNT_DIRSYNC 0x40000000 /* sync creat,link,unlink,rename
* symlink,mkdir,rmdir,mknod */
#define XFSMNT_FLAGS2 0x80000000 /* more flags set in flags2 */

View file

@ -42,6 +42,7 @@
#include "xfs_dfrag.h"
#include "xfs_error.h"
#include "xfs_rw.h"
#include "xfs_vnodeops.h"
/*
* Syssgi interface for swapext
@ -199,7 +200,8 @@ xfs_swap_extents(
if (VN_CACHED(tvp) != 0) {
xfs_inval_cached_trace(&tip->i_iocore, 0, -1, 0, -1);
error = bhv_vop_flushinval_pages(tvp, 0, -1, FI_REMAPF_LOCKED);
error = xfs_flushinval_pages(tip, 0, -1,
FI_REMAPF_LOCKED);
if (error)
goto error0;
}
@ -265,7 +267,7 @@ xfs_swap_extents(
* fields change.
*/
bhv_vop_toss_pages(vp, 0, -1, FI_REMAPF);
xfs_tosspages(ip, 0, -1, FI_REMAPF);
tp = xfs_trans_alloc(mp, XFS_TRANS_SWAPEXT);
if ((error = xfs_trans_reserve(tp, 0,

View file

@ -34,41 +34,41 @@ struct xfs_mount;
* because we only need the core part in the in-core inode.
*/
typedef struct xfs_timestamp {
__int32_t t_sec; /* timestamp seconds */
__int32_t t_nsec; /* timestamp nanoseconds */
__be32 t_sec; /* timestamp seconds */
__be32 t_nsec; /* timestamp nanoseconds */
} xfs_timestamp_t;
/*
* Note: Coordinate changes to this structure with the XFS_DI_* #defines
* below and the offsets table in xfs_ialloc_log_di().
* below, the offsets table in xfs_ialloc_log_di() and struct xfs_icdinode
* in xfs_inode.h.
*/
typedef struct xfs_dinode_core
{
__uint16_t di_magic; /* inode magic # = XFS_DINODE_MAGIC */
__uint16_t di_mode; /* mode and type of file */
__int8_t di_version; /* inode version */
__int8_t di_format; /* format of di_c data */
__uint16_t di_onlink; /* old number of links to file */
__uint32_t di_uid; /* owner's user id */
__uint32_t di_gid; /* owner's group id */
__uint32_t di_nlink; /* number of links to file */
__uint16_t di_projid; /* owner's project id */
__uint8_t di_pad[8]; /* unused, zeroed space */
__uint16_t di_flushiter; /* incremented on flush */
typedef struct xfs_dinode_core {
__be16 di_magic; /* inode magic # = XFS_DINODE_MAGIC */
__be16 di_mode; /* mode and type of file */
__u8 di_version; /* inode version */
__u8 di_format; /* format of di_c data */
__be16 di_onlink; /* old number of links to file */
__be32 di_uid; /* owner's user id */
__be32 di_gid; /* owner's group id */
__be32 di_nlink; /* number of links to file */
__be16 di_projid; /* owner's project id */
__u8 di_pad[8]; /* unused, zeroed space */
__be16 di_flushiter; /* incremented on flush */
xfs_timestamp_t di_atime; /* time last accessed */
xfs_timestamp_t di_mtime; /* time last modified */
xfs_timestamp_t di_ctime; /* time created/inode modified */
xfs_fsize_t di_size; /* number of bytes in file */
xfs_drfsbno_t di_nblocks; /* # of direct & btree blocks used */
xfs_extlen_t di_extsize; /* basic/minimum extent size for file */
xfs_extnum_t di_nextents; /* number of extents in data fork */
xfs_aextnum_t di_anextents; /* number of extents in attribute fork*/
__uint8_t di_forkoff; /* attr fork offs, <<3 for 64b align */
__int8_t di_aformat; /* format of attr fork's data */
__uint32_t di_dmevmask; /* DMIG event mask */
__uint16_t di_dmstate; /* DMIG state info */
__uint16_t di_flags; /* random flags, XFS_DIFLAG_... */
__uint32_t di_gen; /* generation number */
__be64 di_size; /* number of bytes in file */
__be64 di_nblocks; /* # of direct & btree blocks used */
__be32 di_extsize; /* basic/minimum extent size for file */
__be32 di_nextents; /* number of extents in data fork */
__be16 di_anextents; /* number of extents in attribute fork*/
__u8 di_forkoff; /* attr fork offs, <<3 for 64b align */
__s8 di_aformat; /* format of attr fork's data */
__be32 di_dmevmask; /* DMIG event mask */
__be16 di_dmstate; /* DMIG state info */
__be16 di_flags; /* random flags, XFS_DIFLAG_... */
__be32 di_gen; /* generation number */
} xfs_dinode_core_t;
#define DI_MAX_FLUSH 0xffff
@ -81,13 +81,13 @@ typedef struct xfs_dinode
* sure to update the macros like XFS_LITINO below and
* XFS_BMAP_RBLOCK_DSIZE in xfs_bmap_btree.h.
*/
xfs_agino_t di_next_unlinked;/* agi unlinked list ptr */
__be32 di_next_unlinked;/* agi unlinked list ptr */
union {
xfs_bmdr_block_t di_bmbt; /* btree root block */
xfs_bmbt_rec_32_t di_bmx[1]; /* extent list */
xfs_dir2_sf_t di_dir2sf; /* shortform directory v2 */
char di_c[1]; /* local contents */
xfs_dev_t di_dev; /* device for S_IFCHR/S_IFBLK */
__be32 di_dev; /* device for S_IFCHR/S_IFBLK */
uuid_t di_muuid; /* mount point value */
char di_symlink[1]; /* local symbolic link */
} di_u;
@ -175,8 +175,7 @@ typedef enum xfs_dinode_fmt
#define XFS_CFORK_Q_DISK(dcp) ((dcp)->di_forkoff != 0)
#define XFS_CFORK_BOFF(dcp) ((int)((dcp)->di_forkoff << 3))
#define XFS_CFORK_BOFF_DISK(dcp) \
((int)(INT_GET((dcp)->di_forkoff, ARCH_CONVERT) << 3))
#define XFS_CFORK_BOFF_DISK(dcp) ((int)((dcp)->di_forkoff << 3))
#define XFS_CFORK_DSIZE_DISK(dcp,mp) \
(XFS_CFORK_Q_DISK(dcp) ? XFS_CFORK_BOFF_DISK(dcp) : XFS_LITINO(mp))
@ -225,8 +224,8 @@ typedef enum xfs_dinode_fmt
#define XFS_CFORK_NEXTENTS_DISK(dcp,w) \
((w) == XFS_DATA_FORK ? \
INT_GET((dcp)->di_nextents, ARCH_CONVERT) : \
INT_GET((dcp)->di_anextents, ARCH_CONVERT))
be32_to_cpu((dcp)->di_nextents) : \
be16_to_cpu((dcp)->di_anextents))
#define XFS_CFORK_NEXTENTS(dcp,w) \
((w) == XFS_DATA_FORK ? (dcp)->di_nextents : (dcp)->di_anextents)
#define XFS_DFORK_NEXTENTS(dip,w) XFS_CFORK_NEXTENTS_DISK(&(dip)->di_core, w)

View file

@ -43,8 +43,6 @@
#include "xfs_dir2_trace.h"
#include "xfs_error.h"
static int xfs_dir2_put_dirent64_direct(xfs_dir2_put_args_t *pa);
static int xfs_dir2_put_dirent64_uio(xfs_dir2_put_args_t *pa);
void
xfs_dir_mount(
@ -293,47 +291,33 @@ xfs_dir_removename(
* Read a directory.
*/
int
xfs_dir_getdents(
xfs_trans_t *tp,
xfs_readdir(
xfs_inode_t *dp,
uio_t *uio, /* caller's buffer control */
int *eofp) /* out: eof reached */
void *dirent,
size_t bufsize,
xfs_off_t *offset,
filldir_t filldir)
{
int alignment; /* alignment required for ABI */
xfs_dirent_t *dbp; /* malloc'ed buffer */
xfs_dir2_put_t put; /* entry formatting routine */
int rval; /* return value */
int v; /* type-checking value */
vn_trace_entry(dp, __FUNCTION__, (inst_t *)__return_address);
if (XFS_FORCED_SHUTDOWN(dp->i_mount))
return XFS_ERROR(EIO);
ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR);
XFS_STATS_INC(xs_dir_getdents);
/*
* If our caller has given us a single contiguous aligned memory buffer,
* just work directly within that buffer. If it's in user memory,
* lock it down first.
*/
alignment = sizeof(xfs_off_t) - 1;
if ((uio->uio_iovcnt == 1) &&
(((__psint_t)uio->uio_iov[0].iov_base & alignment) == 0) &&
((uio->uio_iov[0].iov_len & alignment) == 0)) {
dbp = NULL;
put = xfs_dir2_put_dirent64_direct;
} else {
dbp = kmem_alloc(sizeof(*dbp) + MAXNAMELEN, KM_SLEEP);
put = xfs_dir2_put_dirent64_uio;
}
*eofp = 0;
if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL)
rval = xfs_dir2_sf_getdents(dp, uio, eofp, dbp, put);
else if ((rval = xfs_dir2_isblock(tp, dp, &v)))
rval = xfs_dir2_sf_getdents(dp, dirent, offset, filldir);
else if ((rval = xfs_dir2_isblock(NULL, dp, &v)))
;
else if (v)
rval = xfs_dir2_block_getdents(tp, dp, uio, eofp, dbp, put);
rval = xfs_dir2_block_getdents(dp, dirent, offset, filldir);
else
rval = xfs_dir2_leaf_getdents(tp, dp, uio, eofp, dbp, put);
if (dbp != NULL)
kmem_free(dbp, sizeof(*dbp) + MAXNAMELEN);
rval = xfs_dir2_leaf_getdents(dp, dirent, bufsize, offset,
filldir);
return rval;
}
@ -612,77 +596,6 @@ xfs_dir2_isleaf(
return 0;
}
/*
* Getdents put routine for 64-bit ABI, direct form.
*/
static int
xfs_dir2_put_dirent64_direct(
xfs_dir2_put_args_t *pa)
{
xfs_dirent_t *idbp; /* dirent pointer */
iovec_t *iovp; /* io vector */
int namelen; /* entry name length */
int reclen; /* entry total length */
uio_t *uio; /* I/O control */
namelen = pa->namelen;
reclen = DIRENTSIZE(namelen);
uio = pa->uio;
/*
* Won't fit in the remaining space.
*/
if (reclen > uio->uio_resid) {
pa->done = 0;
return 0;
}
iovp = uio->uio_iov;
idbp = (xfs_dirent_t *)iovp->iov_base;
iovp->iov_base = (char *)idbp + reclen;
iovp->iov_len -= reclen;
uio->uio_resid -= reclen;
idbp->d_reclen = reclen;
idbp->d_ino = pa->ino;
idbp->d_off = pa->cook;
idbp->d_name[namelen] = '\0';
pa->done = 1;
memcpy(idbp->d_name, pa->name, namelen);
return 0;
}
/*
* Getdents put routine for 64-bit ABI, uio form.
*/
static int
xfs_dir2_put_dirent64_uio(
xfs_dir2_put_args_t *pa)
{
xfs_dirent_t *idbp; /* dirent pointer */
int namelen; /* entry name length */
int reclen; /* entry total length */
int rval; /* return value */
uio_t *uio; /* I/O control */
namelen = pa->namelen;
reclen = DIRENTSIZE(namelen);
uio = pa->uio;
/*
* Won't fit in the remaining space.
*/
if (reclen > uio->uio_resid) {
pa->done = 0;
return 0;
}
idbp = pa->dbp;
idbp->d_reclen = reclen;
idbp->d_ino = pa->ino;
idbp->d_off = pa->cook;
idbp->d_name[namelen] = '\0';
memcpy(idbp->d_name, pa->name, namelen);
rval = xfs_uio_read((caddr_t)idbp, reclen, uio);
pa->done = (rval == 0);
return rval;
}
/*
* Remove the given block from the directory.
* This routine is used for data and free blocks, leaf/node are done

View file

@ -59,21 +59,6 @@ typedef __uint32_t xfs_dir2_db_t;
*/
typedef xfs_off_t xfs_dir2_off_t;
/*
* For getdents, argument struct for put routines.
*/
typedef int (*xfs_dir2_put_t)(struct xfs_dir2_put_args *pa);
typedef struct xfs_dir2_put_args {
xfs_off_t cook; /* cookie of (next) entry */
xfs_intino_t ino; /* inode number */
xfs_dirent_t *dbp; /* buffer pointer */
char *name; /* directory entry name */
int namelen; /* length of name */
int done; /* output: set if value was stored */
xfs_dir2_put_t put; /* put function ptr (i/o) */
struct uio *uio; /* uio control structure */
} xfs_dir2_put_args_t;
/*
* Generic directory interface routines
*/
@ -92,8 +77,6 @@ extern int xfs_dir_removename(struct xfs_trans *tp, struct xfs_inode *dp,
char *name, int namelen, xfs_ino_t ino,
xfs_fsblock_t *first,
struct xfs_bmap_free *flist, xfs_extlen_t tot);
extern int xfs_dir_getdents(struct xfs_trans *tp, struct xfs_inode *dp,
uio_t *uio, int *eofp);
extern int xfs_dir_replace(struct xfs_trans *tp, struct xfs_inode *dp,
char *name, int namelen, xfs_ino_t inum,
xfs_fsblock_t *first,

View file

@ -22,6 +22,7 @@
#include "xfs_inum.h"
#include "xfs_trans.h"
#include "xfs_sb.h"
#include "xfs_ag.h"
#include "xfs_dir2.h"
#include "xfs_dmapi.h"
#include "xfs_mount.h"
@ -432,12 +433,10 @@ xfs_dir2_block_addname(
*/
int /* error */
xfs_dir2_block_getdents(
xfs_trans_t *tp, /* transaction (NULL) */
xfs_inode_t *dp, /* incore inode */
uio_t *uio, /* caller's buffer control */
int *eofp, /* eof reached? (out) */
xfs_dirent_t *dbp, /* caller's buffer */
xfs_dir2_put_t put) /* abi's formatting function */
void *dirent,
xfs_off_t *offset,
filldir_t filldir)
{
xfs_dir2_block_t *block; /* directory block structure */
xfs_dabuf_t *bp; /* buffer for block */
@ -447,31 +446,32 @@ xfs_dir2_block_getdents(
char *endptr; /* end of the data entries */
int error; /* error return value */
xfs_mount_t *mp; /* filesystem mount point */
xfs_dir2_put_args_t p; /* arg package for put rtn */
char *ptr; /* current data entry */
int wantoff; /* starting block offset */
xfs_ino_t ino;
xfs_off_t cook;
mp = dp->i_mount;
/*
* If the block number in the offset is out of range, we're done.
*/
if (xfs_dir2_dataptr_to_db(mp, uio->uio_offset) > mp->m_dirdatablk) {
*eofp = 1;
if (xfs_dir2_dataptr_to_db(mp, *offset) > mp->m_dirdatablk) {
return 0;
}
/*
* Can't read the block, give up, else get dabuf in bp.
*/
if ((error =
xfs_da_read_buf(tp, dp, mp->m_dirdatablk, -1, &bp, XFS_DATA_FORK))) {
error = xfs_da_read_buf(NULL, dp, mp->m_dirdatablk, -1,
&bp, XFS_DATA_FORK);
if (error)
return error;
}
ASSERT(bp != NULL);
/*
* Extract the byte offset we start at from the seek pointer.
* We'll skip entries before this.
*/
wantoff = xfs_dir2_dataptr_to_off(mp, uio->uio_offset);
wantoff = xfs_dir2_dataptr_to_off(mp, *offset);
block = bp->data;
xfs_dir2_data_check(dp, bp);
/*
@ -480,9 +480,7 @@ xfs_dir2_block_getdents(
btp = xfs_dir2_block_tail_p(mp, block);
ptr = (char *)block->u;
endptr = (char *)xfs_dir2_block_leaf_p(btp);
p.dbp = dbp;
p.put = put;
p.uio = uio;
/*
* Loop over the data portion of the block.
* Each object is a real entry (dep) or an unused one (dup).
@ -508,33 +506,24 @@ xfs_dir2_block_getdents(
*/
if ((char *)dep - (char *)block < wantoff)
continue;
/*
* Set up argument structure for put routine.
*/
p.namelen = dep->namelen;
p.cook = xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk,
cook = xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk,
ptr - (char *)block);
p.ino = be64_to_cpu(dep->inumber);
ino = be64_to_cpu(dep->inumber);
#if XFS_BIG_INUMS
p.ino += mp->m_inoadd;
ino += mp->m_inoadd;
#endif
p.name = (char *)dep->name;
/*
* Put the entry in the caller's buffer.
*/
error = p.put(&p);
/*
* If it didn't fit, set the final offset to here & return.
*/
if (!p.done) {
uio->uio_offset =
xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk,
if (filldir(dirent, dep->name, dep->namelen, cook,
ino, DT_UNKNOWN)) {
*offset = xfs_dir2_db_off_to_dataptr(mp,
mp->m_dirdatablk,
(char *)dep - (char *)block);
xfs_da_brelse(tp, bp);
return error;
xfs_da_brelse(NULL, bp);
return 0;
}
}
@ -542,13 +531,8 @@ xfs_dir2_block_getdents(
* Reached the end of the block.
* Set the offset to a non-existent block 1 and return.
*/
*eofp = 1;
uio->uio_offset =
xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk + 1, 0);
xfs_da_brelse(tp, bp);
*offset = xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk + 1, 0);
xfs_da_brelse(NULL, bp);
return 0;
}

View file

@ -80,9 +80,8 @@ xfs_dir2_block_leaf_p(xfs_dir2_block_tail_t *btp)
* Function declarations.
*/
extern int xfs_dir2_block_addname(struct xfs_da_args *args);
extern int xfs_dir2_block_getdents(struct xfs_trans *tp, struct xfs_inode *dp,
struct uio *uio, int *eofp,
struct xfs_dirent *dbp, xfs_dir2_put_t put);
extern int xfs_dir2_block_getdents(struct xfs_inode *dp, void *dirent,
xfs_off_t *offset, filldir_t filldir);
extern int xfs_dir2_block_lookup(struct xfs_da_args *args);
extern int xfs_dir2_block_removename(struct xfs_da_args *args);
extern int xfs_dir2_block_replace(struct xfs_da_args *args);

View file

@ -22,6 +22,7 @@
#include "xfs_inum.h"
#include "xfs_trans.h"
#include "xfs_sb.h"
#include "xfs_ag.h"
#include "xfs_dir2.h"
#include "xfs_dmapi.h"
#include "xfs_mount.h"

View file

@ -749,12 +749,11 @@ xfs_dir2_leaf_compact_x1(
*/
int /* error */
xfs_dir2_leaf_getdents(
xfs_trans_t *tp, /* transaction pointer */
xfs_inode_t *dp, /* incore directory inode */
uio_t *uio, /* I/O control & vectors */
int *eofp, /* out: reached end of dir */
xfs_dirent_t *dbp, /* caller's buffer */
xfs_dir2_put_t put) /* ABI formatting routine */
void *dirent,
size_t bufsize,
xfs_off_t *offset,
filldir_t filldir)
{
xfs_dabuf_t *bp; /* data block buffer */
int byteoff; /* offset in current block */
@ -763,7 +762,6 @@ xfs_dir2_leaf_getdents(
xfs_dir2_data_t *data; /* data block structure */
xfs_dir2_data_entry_t *dep; /* data entry */
xfs_dir2_data_unused_t *dup; /* unused entry */
int eof; /* reached end of directory */
int error = 0; /* error return value */
int i; /* temporary loop index */
int j; /* temporary loop index */
@ -776,46 +774,38 @@ xfs_dir2_leaf_getdents(
xfs_mount_t *mp; /* filesystem mount point */
xfs_dir2_off_t newoff; /* new curoff after new blk */
int nmap; /* mappings to ask xfs_bmapi */
xfs_dir2_put_args_t *p; /* formatting arg bundle */
char *ptr = NULL; /* pointer to current data */
int ra_current; /* number of read-ahead blks */
int ra_index; /* *map index for read-ahead */
int ra_offset; /* map entry offset for ra */
int ra_want; /* readahead count wanted */
xfs_ino_t ino;
/*
* If the offset is at or past the largest allowed value,
* give up right away, return eof.
* give up right away.
*/
if (uio->uio_offset >= XFS_DIR2_MAX_DATAPTR) {
*eofp = 1;
if (*offset >= XFS_DIR2_MAX_DATAPTR)
return 0;
}
mp = dp->i_mount;
/*
* Setup formatting arguments.
*/
p = kmem_alloc(sizeof(*p), KM_SLEEP);
p->dbp = dbp;
p->put = put;
p->uio = uio;
/*
* Set up to bmap a number of blocks based on the caller's
* buffer size, the directory block size, and the filesystem
* block size.
*/
map_size =
howmany(uio->uio_resid + mp->m_dirblksize,
mp->m_sb.sb_blocksize);
map_size = howmany(bufsize + mp->m_dirblksize, mp->m_sb.sb_blocksize);
map = kmem_alloc(map_size * sizeof(*map), KM_SLEEP);
map_valid = ra_index = ra_offset = ra_current = map_blocks = 0;
bp = NULL;
eof = 1;
/*
* Inside the loop we keep the main offset value as a byte offset
* in the directory file.
*/
curoff = xfs_dir2_dataptr_to_byte(mp, uio->uio_offset);
curoff = xfs_dir2_dataptr_to_byte(mp, *offset);
/*
* Force this conversion through db so we truncate the offset
* down to get the start of the data block.
@ -836,7 +826,7 @@ xfs_dir2_leaf_getdents(
* take it out of the mapping.
*/
if (bp) {
xfs_da_brelse(tp, bp);
xfs_da_brelse(NULL, bp);
bp = NULL;
map_blocks -= mp->m_dirblkfsbs;
/*
@ -862,8 +852,9 @@ xfs_dir2_leaf_getdents(
/*
* Recalculate the readahead blocks wanted.
*/
ra_want = howmany(uio->uio_resid + mp->m_dirblksize,
ra_want = howmany(bufsize + mp->m_dirblksize,
mp->m_sb.sb_blocksize) - 1;
/*
* If we don't have as many as we want, and we haven't
* run out of data blocks, get some more mappings.
@ -876,7 +867,7 @@ xfs_dir2_leaf_getdents(
* we already have in the table.
*/
nmap = map_size - map_valid;
error = xfs_bmapi(tp, dp,
error = xfs_bmapi(NULL, dp,
map_off,
xfs_dir2_byte_to_da(mp,
XFS_DIR2_LEAF_OFFSET) - map_off,
@ -939,7 +930,7 @@ xfs_dir2_leaf_getdents(
* mapping.
*/
curdb = xfs_dir2_da_to_db(mp, map->br_startoff);
error = xfs_da_read_buf(tp, dp, map->br_startoff,
error = xfs_da_read_buf(NULL, dp, map->br_startoff,
map->br_blockcount >= mp->m_dirblkfsbs ?
XFS_FSB_TO_DADDR(mp, map->br_startblock) :
-1,
@ -982,7 +973,7 @@ xfs_dir2_leaf_getdents(
* is a very rare case.
*/
else if (i > ra_current) {
(void)xfs_da_reada_buf(tp, dp,
(void)xfs_da_reada_buf(NULL, dp,
map[ra_index].br_startoff +
ra_offset, XFS_DATA_FORK);
ra_current = i;
@ -1089,46 +1080,39 @@ xfs_dir2_leaf_getdents(
*/
dep = (xfs_dir2_data_entry_t *)ptr;
p->namelen = dep->namelen;
length = xfs_dir2_data_entsize(dep->namelen);
length = xfs_dir2_data_entsize(p->namelen);
p->cook = xfs_dir2_byte_to_dataptr(mp, curoff + length);
p->ino = be64_to_cpu(dep->inumber);
ino = be64_to_cpu(dep->inumber);
#if XFS_BIG_INUMS
p->ino += mp->m_inoadd;
ino += mp->m_inoadd;
#endif
p->name = (char *)dep->name;
error = p->put(p);
/*
* Won't fit. Return to caller.
*/
if (!p->done) {
eof = 0;
if (filldir(dirent, dep->name, dep->namelen,
xfs_dir2_byte_to_dataptr(mp, curoff + length),
ino, DT_UNKNOWN))
break;
}
/*
* Advance to next entry in the block.
*/
ptr += length;
curoff += length;
bufsize -= length;
}
/*
* All done. Set output offset value to current offset.
*/
*eofp = eof;
if (curoff > xfs_dir2_dataptr_to_byte(mp, XFS_DIR2_MAX_DATAPTR))
uio->uio_offset = XFS_DIR2_MAX_DATAPTR;
*offset = XFS_DIR2_MAX_DATAPTR;
else
uio->uio_offset = xfs_dir2_byte_to_dataptr(mp, curoff);
*offset = xfs_dir2_byte_to_dataptr(mp, curoff);
kmem_free(map, map_size * sizeof(*map));
kmem_free(p, sizeof(*p));
if (bp)
xfs_da_brelse(tp, bp);
xfs_da_brelse(NULL, bp);
return error;
}

View file

@ -232,9 +232,9 @@ extern void xfs_dir2_leaf_compact(struct xfs_da_args *args,
extern void xfs_dir2_leaf_compact_x1(struct xfs_dabuf *bp, int *indexp,
int *lowstalep, int *highstalep,
int *lowlogp, int *highlogp);
extern int xfs_dir2_leaf_getdents(struct xfs_trans *tp, struct xfs_inode *dp,
struct uio *uio, int *eofp,
struct xfs_dirent *dbp, xfs_dir2_put_t put);
extern int xfs_dir2_leaf_getdents(struct xfs_inode *dp, void *dirent,
size_t bufsize, xfs_off_t *offset,
filldir_t filldir);
extern int xfs_dir2_leaf_init(struct xfs_da_args *args, xfs_dir2_db_t bno,
struct xfs_dabuf **bpp, int magic);
extern void xfs_dir2_leaf_log_ents(struct xfs_trans *tp, struct xfs_dabuf *bp,

View file

@ -22,6 +22,7 @@
#include "xfs_inum.h"
#include "xfs_trans.h"
#include "xfs_sb.h"
#include "xfs_ag.h"
#include "xfs_dir2.h"
#include "xfs_dmapi.h"
#include "xfs_mount.h"

View file

@ -22,6 +22,7 @@
#include "xfs_inum.h"
#include "xfs_trans.h"
#include "xfs_sb.h"
#include "xfs_ag.h"
#include "xfs_dir2.h"
#include "xfs_dmapi.h"
#include "xfs_mount.h"
@ -695,19 +696,18 @@ xfs_dir2_sf_create(
int /* error */
xfs_dir2_sf_getdents(
xfs_inode_t *dp, /* incore directory inode */
uio_t *uio, /* caller's buffer control */
int *eofp, /* eof reached? (out) */
xfs_dirent_t *dbp, /* caller's buffer */
xfs_dir2_put_t put) /* abi's formatting function */
void *dirent,
xfs_off_t *offset,
filldir_t filldir)
{
int error; /* error return value */
int i; /* shortform entry number */
xfs_mount_t *mp; /* filesystem mount point */
xfs_dir2_dataptr_t off; /* current entry's offset */
xfs_dir2_put_args_t p; /* arg package for put rtn */
xfs_dir2_sf_entry_t *sfep; /* shortform directory entry */
xfs_dir2_sf_t *sfp; /* shortform structure */
xfs_off_t dir_offset;
xfs_dir2_dataptr_t dot_offset;
xfs_dir2_dataptr_t dotdot_offset;
xfs_ino_t ino;
mp = dp->i_mount;
@ -720,8 +720,6 @@ xfs_dir2_sf_getdents(
return XFS_ERROR(EIO);
}
dir_offset = uio->uio_offset;
ASSERT(dp->i_df.if_bytes == dp->i_d.di_size);
ASSERT(dp->i_df.if_u1.if_data != NULL);
@ -732,108 +730,78 @@ xfs_dir2_sf_getdents(
/*
* If the block number in the offset is out of range, we're done.
*/
if (xfs_dir2_dataptr_to_db(mp, dir_offset) > mp->m_dirdatablk) {
*eofp = 1;
if (xfs_dir2_dataptr_to_db(mp, *offset) > mp->m_dirdatablk)
return 0;
}
/*
* Set up putargs structure.
* Precalculate offsets for . and .. as we will always need them.
*
* XXX(hch): the second argument is sometimes 0 and sometimes
* mp->m_dirdatablk.
*/
p.dbp = dbp;
p.put = put;
p.uio = uio;
dot_offset = xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk,
XFS_DIR2_DATA_DOT_OFFSET);
dotdot_offset = xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk,
XFS_DIR2_DATA_DOTDOT_OFFSET);
/*
* Put . entry unless we're starting past it.
*/
if (dir_offset <=
xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk,
XFS_DIR2_DATA_DOT_OFFSET)) {
p.cook = xfs_dir2_db_off_to_dataptr(mp, 0,
XFS_DIR2_DATA_DOTDOT_OFFSET);
p.ino = dp->i_ino;
if (*offset <= dot_offset) {
ino = dp->i_ino;
#if XFS_BIG_INUMS
p.ino += mp->m_inoadd;
ino += mp->m_inoadd;
#endif
p.name = ".";
p.namelen = 1;
error = p.put(&p);
if (!p.done) {
uio->uio_offset =
xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk,
XFS_DIR2_DATA_DOT_OFFSET);
return error;
if (filldir(dirent, ".", 1, dotdot_offset, ino, DT_DIR)) {
*offset = dot_offset;
return 0;
}
}
/*
* Put .. entry unless we're starting past it.
*/
if (dir_offset <=
xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk,
XFS_DIR2_DATA_DOTDOT_OFFSET)) {
p.cook = xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk,
XFS_DIR2_DATA_FIRST_OFFSET);
p.ino = xfs_dir2_sf_get_inumber(sfp, &sfp->hdr.parent);
if (*offset <= dotdot_offset) {
off = xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk,
XFS_DIR2_DATA_FIRST_OFFSET);
ino = xfs_dir2_sf_get_inumber(sfp, &sfp->hdr.parent);
#if XFS_BIG_INUMS
p.ino += mp->m_inoadd;
ino += mp->m_inoadd;
#endif
p.name = "..";
p.namelen = 2;
error = p.put(&p);
if (!p.done) {
uio->uio_offset =
xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk,
XFS_DIR2_DATA_DOTDOT_OFFSET);
return error;
if (filldir(dirent, "..", 2, off, ino, DT_DIR)) {
*offset = dotdot_offset;
return 0;
}
}
/*
* Loop while there are more entries and put'ing works.
*/
for (i = 0, sfep = xfs_dir2_sf_firstentry(sfp);
i < sfp->hdr.count;
i++, sfep = xfs_dir2_sf_nextentry(sfp, sfep)) {
sfep = xfs_dir2_sf_firstentry(sfp);
for (i = 0; i < sfp->hdr.count; i++) {
off = xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk,
xfs_dir2_sf_get_offset(sfep));
if (dir_offset > off)
if (*offset > off) {
sfep = xfs_dir2_sf_nextentry(sfp, sfep);
continue;
p.namelen = sfep->namelen;
p.cook = xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk,
xfs_dir2_sf_get_offset(sfep) +
xfs_dir2_data_entsize(p.namelen));
p.ino = xfs_dir2_sf_get_inumber(sfp, xfs_dir2_sf_inumberp(sfep));
#if XFS_BIG_INUMS
p.ino += mp->m_inoadd;
#endif
p.name = (char *)sfep->name;
error = p.put(&p);
if (!p.done) {
uio->uio_offset = off;
return error;
}
ino = xfs_dir2_sf_get_inumber(sfp, xfs_dir2_sf_inumberp(sfep));
#if XFS_BIG_INUMS
ino += mp->m_inoadd;
#endif
if (filldir(dirent, sfep->name, sfep->namelen,
off + xfs_dir2_data_entsize(sfep->namelen),
ino, DT_UNKNOWN)) {
*offset = off;
return 0;
}
sfep = xfs_dir2_sf_nextentry(sfp, sfep);
}
/*
* They all fit.
*/
*eofp = 1;
uio->uio_offset =
xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk + 1, 0);
*offset = xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk + 1, 0);
return 0;
}

View file

@ -169,9 +169,8 @@ extern int xfs_dir2_block_to_sf(struct xfs_da_args *args, struct xfs_dabuf *bp,
int size, xfs_dir2_sf_hdr_t *sfhp);
extern int xfs_dir2_sf_addname(struct xfs_da_args *args);
extern int xfs_dir2_sf_create(struct xfs_da_args *args, xfs_ino_t pino);
extern int xfs_dir2_sf_getdents(struct xfs_inode *dp, struct uio *uio,
int *eofp, struct xfs_dirent *dbp,
xfs_dir2_put_t put);
extern int xfs_dir2_sf_getdents(struct xfs_inode *dp, void *dirent,
xfs_off_t *offset, filldir_t filldir);
extern int xfs_dir2_sf_lookup(struct xfs_da_args *args);
extern int xfs_dir2_sf_removename(struct xfs_da_args *args);
extern int xfs_dir2_sf_replace(struct xfs_da_args *args);

View file

@ -67,17 +67,15 @@ typedef enum {
#define HAVE_DM_RIGHT_T
/* Defines for determining if an event message should be sent. */
#define DM_EVENT_ENABLED(vfsp, ip, event) ( \
unlikely ((vfsp)->vfs_flag & VFS_DMI) && \
#ifdef HAVE_DMAPI
#define DM_EVENT_ENABLED(ip, event) ( \
unlikely ((ip)->i_mount->m_flags & XFS_MOUNT_DMAPI) && \
( ((ip)->i_d.di_dmevmask & (1 << event)) || \
((ip)->i_mount->m_dmevmask & (1 << event)) ) \
)
#define DM_EVENT_ENABLED_IO(vfsp, io, event) ( \
unlikely ((vfsp)->vfs_flag & VFS_DMI) && \
( ((io)->io_dmevmask & (1 << event)) || \
((io)->io_mount->m_dmevmask & (1 << event)) ) \
)
#else
#define DM_EVENT_ENABLED(ip, event) (0)
#endif
#define DM_XFS_VALID_FS_EVENTS ( \
(1 << DM_EVENT_PREUNMOUNT) | \
@ -170,7 +168,4 @@ typedef enum {
DM_FLAGS_NDELAY : 0)
#define AT_DELAY_FLAG(f) ((f&ATTR_NONBLOCK) ? DM_FLAGS_NDELAY : 0)
extern struct bhv_module_vfsops xfs_dmops;
#endif /* __XFS_DMAPI_H__ */

View file

@ -19,18 +19,51 @@
#include "xfs_fs.h"
#include "xfs_types.h"
#include "xfs_log.h"
#include "xfs_inum.h"
#include "xfs_trans.h"
#include "xfs_sb.h"
#include "xfs_ag.h"
#include "xfs_dir2.h"
#include "xfs_dmapi.h"
#include "xfs_inum.h"
#include "xfs_ag.h"
#include "xfs_mount.h"
#include "xfs_clnt.h"
xfs_dmops_t xfs_dmcore_stub = {
static struct xfs_dmops xfs_dmcore_stub = {
.xfs_send_data = (xfs_send_data_t)fs_nosys,
.xfs_send_mmap = (xfs_send_mmap_t)fs_noerr,
.xfs_send_destroy = (xfs_send_destroy_t)fs_nosys,
.xfs_send_namesp = (xfs_send_namesp_t)fs_nosys,
.xfs_send_unmount = (xfs_send_unmount_t)fs_noval,
.xfs_send_mount = (xfs_send_mount_t)fs_nosys,
.xfs_send_unmount = (xfs_send_unmount_t)fs_noerr,
};
int
xfs_dmops_get(struct xfs_mount *mp, struct xfs_mount_args *args)
{
if (args->flags & XFSMNT_DMAPI) {
struct xfs_dmops *ops;
ops = symbol_get(xfs_dmcore_xfs);
if (!ops) {
request_module("xfs_dmapi");
ops = symbol_get(xfs_dmcore_xfs);
}
if (!ops) {
cmn_err(CE_WARN, "XFS: no dmapi support available.");
return EINVAL;
}
mp->m_dm_ops = ops;
} else {
mp->m_dm_ops = &xfs_dmcore_stub;
}
return 0;
}
void
xfs_dmops_put(struct xfs_mount *mp)
{
if (mp->m_dm_ops != &xfs_dmcore_stub)
symbol_put(xfs_dmcore_xfs);
}

View file

@ -22,6 +22,7 @@
#include "xfs_inum.h"
#include "xfs_trans.h"
#include "xfs_sb.h"
#include "xfs_ag.h"
#include "xfs_dir2.h"
#include "xfs_dmapi.h"
#include "xfs_mount.h"
@ -132,10 +133,14 @@ xfs_errortag_add(int error_tag, xfs_mount_t *mp)
}
int
xfs_errortag_clearall_umount(int64_t fsid, char *fsname, int loud)
xfs_errortag_clearall(xfs_mount_t *mp, int loud)
{
int i;
int64_t fsid;
int cleared = 0;
int i;
memcpy(&fsid, mp->m_fixedfsid, sizeof(xfs_fsid_t));
for (i = 0; i < XFS_NUM_INJECT_ERROR; i++) {
if ((fsid == 0LL || xfs_etest_fsid[i] == fsid) &&
@ -154,20 +159,10 @@ xfs_errortag_clearall_umount(int64_t fsid, char *fsname, int loud)
if (loud || cleared)
cmn_err(CE_WARN,
"Cleared all XFS error tags for filesystem \"%s\"",
fsname);
mp->m_fsname);
return 0;
}
int
xfs_errortag_clearall(xfs_mount_t *mp)
{
int64_t fsid;
memcpy(&fsid, mp->m_fixedfsid, sizeof(xfs_fsid_t));
return xfs_errortag_clearall_umount(fsid, mp->m_fsname, 1);
}
#endif /* DEBUG || INDUCE_IO_ERROR */
static void

View file

@ -144,12 +144,11 @@ extern void xfs_error_test_init(void);
#endif /* __ANSI_CPP__ */
extern int xfs_errortag_add(int error_tag, xfs_mount_t *mp);
extern int xfs_errortag_clearall(xfs_mount_t *mp);
extern int xfs_errortag_clearall_umount(int64_t fsid, char *fsname, int loud);
extern int xfs_errortag_clearall(xfs_mount_t *mp, int loud);
#else
#define XFS_TEST_ERROR(expr, mp, tag, rf) (expr)
#define xfs_errortag_add(tag, mp) (ENOSYS)
#define xfs_errortag_clearall(mp) (ENOSYS)
#define xfs_errortag_clearall(mp, loud) (ENOSYS)
#endif /* (DEBUG || INDUCE_IO_ERROR) */
/*

View file

@ -23,6 +23,7 @@
#include "xfs_trans.h"
#include "xfs_buf_item.h"
#include "xfs_sb.h"
#include "xfs_ag.h"
#include "xfs_dmapi.h"
#include "xfs_mount.h"
#include "xfs_trans_priv.h"

View file

@ -136,7 +136,6 @@ xfs_growfs_data_private(
xfs_rfsblock_t nfree;
xfs_agnumber_t oagcount;
int pct;
xfs_sb_t *sbp;
xfs_trans_t *tp;
nb = in->newblocks;
@ -175,7 +174,7 @@ xfs_growfs_data_private(
memset(&mp->m_perag[oagcount], 0,
(nagcount - oagcount) * sizeof(xfs_perag_t));
mp->m_flags |= XFS_MOUNT_32BITINODES;
nagimax = xfs_initialize_perag(XFS_MTOVFS(mp), mp, nagcount);
nagimax = xfs_initialize_perag(mp, nagcount);
up_write(&mp->m_peraglock);
}
tp = xfs_trans_alloc(mp, XFS_TRANS_GROWFS);
@ -377,8 +376,7 @@ xfs_growfs_data_private(
error, agno);
break;
}
sbp = XFS_BUF_TO_SBP(bp);
xfs_xlatesb(sbp, &mp->m_sb, -1, XFS_SB_ALL_BITS);
xfs_sb_to_disk(XFS_BUF_TO_SBP(bp), &mp->m_sb, XFS_SB_ALL_BITS);
/*
* If we get an error writing out the alternate superblocks,
* just issue a warning and continue. The real work is
@ -435,10 +433,10 @@ xfs_growfs_data(
xfs_growfs_data_t *in)
{
int error;
if (!cpsema(&mp->m_growlock))
if (!mutex_trylock(&mp->m_growlock))
return XFS_ERROR(EWOULDBLOCK);
error = xfs_growfs_data_private(mp, in);
vsema(&mp->m_growlock);
mutex_unlock(&mp->m_growlock);
return error;
}
@ -448,10 +446,10 @@ xfs_growfs_log(
xfs_growfs_log_t *in)
{
int error;
if (!cpsema(&mp->m_growlock))
if (!mutex_trylock(&mp->m_growlock))
return XFS_ERROR(EWOULDBLOCK);
error = xfs_growfs_log_private(mp, in);
vsema(&mp->m_growlock);
mutex_unlock(&mp->m_growlock);
return error;
}
@ -628,8 +626,7 @@ xfs_fs_goingdown(
{
switch (inflags) {
case XFS_FSOP_GOING_FLAGS_DEFAULT: {
struct bhv_vfs *vfsp = XFS_MTOVFS(mp);
struct super_block *sb = freeze_bdev(vfsp->vfs_super->s_bdev);
struct super_block *sb = freeze_bdev(mp->m_super->s_bdev);
if (sb && !IS_ERR(sb)) {
xfs_force_shutdown(mp, SHUTDOWN_FORCE_UMOUNT);

View file

@ -293,9 +293,9 @@ xfs_ialloc_ag_alloc(
xfs_biozero(fbuf, 0, ninodes << args.mp->m_sb.sb_inodelog);
for (i = 0; i < ninodes; i++) {
free = XFS_MAKE_IPTR(args.mp, fbuf, i);
INT_SET(free->di_core.di_magic, ARCH_CONVERT, XFS_DINODE_MAGIC);
INT_SET(free->di_core.di_version, ARCH_CONVERT, version);
INT_SET(free->di_next_unlinked, ARCH_CONVERT, NULLAGINO);
free->di_core.di_magic = cpu_to_be16(XFS_DINODE_MAGIC);
free->di_core.di_version = version;
free->di_next_unlinked = cpu_to_be32(NULLAGINO);
xfs_ialloc_log_di(tp, fbuf, i,
XFS_DI_CORE_BITS | XFS_DI_NEXT_UNLINKED);
}

View file

@ -30,14 +30,9 @@ struct xfs_trans;
#define XFS_IALLOC_BLOCKS(mp) (mp)->m_ialloc_blks
/*
* For small block file systems, move inodes in clusters of this size.
* When we don't have a lot of memory, however, we go a bit smaller
* to reduce the number of AGI and ialloc btree blocks we need to keep
* around for xfs_dilocate(). We choose which one to use in
* xfs_mount_int().
* Move inodes in clusters of this size.
*/
#define XFS_INODE_BIG_CLUSTER_SIZE 8192
#define XFS_INODE_SMALL_CLUSTER_SIZE 4096
#define XFS_INODE_CLUSTER_SIZE(mp) (mp)->m_inode_cluster_size
/*

View file

@ -39,132 +39,14 @@
#include "xfs_quota.h"
#include "xfs_utils.h"
/*
* Initialize the inode hash table for the newly mounted file system.
* Choose an initial table size based on user specified value, else
* use a simple algorithm using the maximum number of inodes as an
* indicator for table size, and clamp it between one and some large
* number of pages.
*/
void
xfs_ihash_init(xfs_mount_t *mp)
{
__uint64_t icount;
uint i;
if (!mp->m_ihsize) {
icount = mp->m_maxicount ? mp->m_maxicount :
(mp->m_sb.sb_dblocks << mp->m_sb.sb_inopblog);
mp->m_ihsize = 1 << max_t(uint, 8,
(xfs_highbit64(icount) + 1) / 2);
mp->m_ihsize = min_t(uint, mp->m_ihsize,
(64 * NBPP) / sizeof(xfs_ihash_t));
}
mp->m_ihash = kmem_zalloc_greedy(&mp->m_ihsize,
NBPC * sizeof(xfs_ihash_t),
mp->m_ihsize * sizeof(xfs_ihash_t),
KM_SLEEP | KM_MAYFAIL | KM_LARGE);
mp->m_ihsize /= sizeof(xfs_ihash_t);
for (i = 0; i < mp->m_ihsize; i++)
rwlock_init(&(mp->m_ihash[i].ih_lock));
}
/*
* Free up structures allocated by xfs_ihash_init, at unmount time.
*/
void
xfs_ihash_free(xfs_mount_t *mp)
{
kmem_free(mp->m_ihash, mp->m_ihsize * sizeof(xfs_ihash_t));
mp->m_ihash = NULL;
}
/*
* Initialize the inode cluster hash table for the newly mounted file system.
* Its size is derived from the ihash table size.
*/
void
xfs_chash_init(xfs_mount_t *mp)
{
uint i;
mp->m_chsize = max_t(uint, 1, mp->m_ihsize /
(XFS_INODE_CLUSTER_SIZE(mp) >> mp->m_sb.sb_inodelog));
mp->m_chsize = min_t(uint, mp->m_chsize, mp->m_ihsize);
mp->m_chash = (xfs_chash_t *)kmem_zalloc(mp->m_chsize
* sizeof(xfs_chash_t),
KM_SLEEP | KM_LARGE);
for (i = 0; i < mp->m_chsize; i++) {
spinlock_init(&mp->m_chash[i].ch_lock,"xfshash");
}
}
/*
* Free up structures allocated by xfs_chash_init, at unmount time.
*/
void
xfs_chash_free(xfs_mount_t *mp)
{
int i;
for (i = 0; i < mp->m_chsize; i++) {
spinlock_destroy(&mp->m_chash[i].ch_lock);
}
kmem_free(mp->m_chash, mp->m_chsize*sizeof(xfs_chash_t));
mp->m_chash = NULL;
}
/*
* Try to move an inode to the front of its hash list if possible
* (and if its not there already). Called right after obtaining
* the list version number and then dropping the read_lock on the
* hash list in question (which is done right after looking up the
* inode in question...).
*/
STATIC void
xfs_ihash_promote(
xfs_ihash_t *ih,
xfs_inode_t *ip,
ulong version)
{
xfs_inode_t *iq;
if ((ip->i_prevp != &ih->ih_next) && write_trylock(&ih->ih_lock)) {
if (likely(version == ih->ih_version)) {
/* remove from list */
if ((iq = ip->i_next)) {
iq->i_prevp = ip->i_prevp;
}
*ip->i_prevp = iq;
/* insert at list head */
iq = ih->ih_next;
iq->i_prevp = &ip->i_next;
ip->i_next = iq;
ip->i_prevp = &ih->ih_next;
ih->ih_next = ip;
}
write_unlock(&ih->ih_lock);
}
}
/*
* Look up an inode by number in the given file system.
* The inode is looked up in the hash table for the file system
* represented by the mount point parameter mp. Each bucket of
* the hash table is guarded by an individual semaphore.
* The inode is looked up in the cache held in each AG.
* If the inode is found in the cache, attach it to the provided
* vnode.
*
* If the inode is found in the hash table, its corresponding vnode
* is obtained with a call to vn_get(). This call takes care of
* coordination with the reclamation of the inode and vnode. Note
* that the vmap structure is filled in while holding the hash lock.
* This gives us the state of the inode/vnode when we found it and
* is used for coordination in vn_get().
*
* If it is not in core, read it in from the file system's device and
* add the inode into the hash table.
* If it is not in core, read it in from the file system's device,
* add it to the cache and attach the provided vnode.
*
* The inode is locked according to the value of the lock_flags parameter.
* This flag parameter indicates how and if the inode's IO lock and inode lock
@ -192,274 +74,241 @@ xfs_iget_core(
xfs_inode_t **ipp,
xfs_daddr_t bno)
{
xfs_ihash_t *ih;
xfs_inode_t *ip;
xfs_inode_t *iq;
bhv_vnode_t *inode_vp;
ulong version;
int error;
/* REFERENCED */
xfs_chash_t *ch;
xfs_chashlist_t *chl, *chlnew;
SPLDECL(s);
xfs_icluster_t *icl, *new_icl = NULL;
unsigned long first_index, mask;
xfs_perag_t *pag;
xfs_agino_t agino;
/* the radix tree exists only in inode capable AGs */
if (XFS_INO_TO_AGNO(mp, ino) >= mp->m_maxagi)
return EINVAL;
ih = XFS_IHASH(mp, ino);
/* get the perag structure and ensure that it's inode capable */
pag = xfs_get_perag(mp, ino);
if (!pag->pagi_inodeok)
return EINVAL;
ASSERT(pag->pag_ici_init);
agino = XFS_INO_TO_AGINO(mp, ino);
again:
read_lock(&ih->ih_lock);
read_lock(&pag->pag_ici_lock);
ip = radix_tree_lookup(&pag->pag_ici_root, agino);
for (ip = ih->ih_next; ip != NULL; ip = ip->i_next) {
if (ip->i_ino == ino) {
if (ip != NULL) {
/*
* If INEW is set this inode is being set up
* we need to pause and try again.
*/
if (xfs_iflags_test(ip, XFS_INEW)) {
read_unlock(&pag->pag_ici_lock);
delay(1);
XFS_STATS_INC(xs_ig_frecycle);
goto again;
}
inode_vp = XFS_ITOV_NULL(ip);
if (inode_vp == NULL) {
/*
* If INEW is set this inode is being set up
* If IRECLAIM is set this inode is
* on its way out of the system,
* we need to pause and try again.
*/
if (xfs_iflags_test(ip, XFS_INEW)) {
read_unlock(&ih->ih_lock);
if (xfs_iflags_test(ip, XFS_IRECLAIM)) {
read_unlock(&pag->pag_ici_lock);
delay(1);
XFS_STATS_INC(xs_ig_frecycle);
goto again;
}
ASSERT(xfs_iflags_test(ip, XFS_IRECLAIMABLE));
inode_vp = XFS_ITOV_NULL(ip);
if (inode_vp == NULL) {
/*
* If IRECLAIM is set this inode is
* on its way out of the system,
* we need to pause and try again.
*/
if (xfs_iflags_test(ip, XFS_IRECLAIM)) {
read_unlock(&ih->ih_lock);
delay(1);
XFS_STATS_INC(xs_ig_frecycle);
goto again;
}
ASSERT(xfs_iflags_test(ip, XFS_IRECLAIMABLE));
/*
* If lookup is racing with unlink, then we
* should return an error immediately so we
* don't remove it from the reclaim list and
* potentially leak the inode.
*/
if ((ip->i_d.di_mode == 0) &&
!(flags & XFS_IGET_CREATE)) {
read_unlock(&ih->ih_lock);
return ENOENT;
}
/*
* There may be transactions sitting in the
* incore log buffers or being flushed to disk
* at this time. We can't clear the
* XFS_IRECLAIMABLE flag until these
* transactions have hit the disk, otherwise we
* will void the guarantee the flag provides
* xfs_iunpin()
*/
if (xfs_ipincount(ip)) {
read_unlock(&ih->ih_lock);
xfs_log_force(mp, 0,
XFS_LOG_FORCE|XFS_LOG_SYNC);
XFS_STATS_INC(xs_ig_frecycle);
goto again;
}
vn_trace_exit(vp, "xfs_iget.alloc",
(inst_t *)__return_address);
XFS_STATS_INC(xs_ig_found);
xfs_iflags_clear(ip, XFS_IRECLAIMABLE);
version = ih->ih_version;
read_unlock(&ih->ih_lock);
xfs_ihash_promote(ih, ip, version);
XFS_MOUNT_ILOCK(mp);
list_del_init(&ip->i_reclaim);
XFS_MOUNT_IUNLOCK(mp);
goto finish_inode;
} else if (vp != inode_vp) {
struct inode *inode = vn_to_inode(inode_vp);
/* The inode is being torn down, pause and
* try again.
*/
if (inode->i_state & (I_FREEING | I_CLEAR)) {
read_unlock(&ih->ih_lock);
delay(1);
XFS_STATS_INC(xs_ig_frecycle);
goto again;
}
/* Chances are the other vnode (the one in the inode) is being torn
* down right now, and we landed on top of it. Question is, what do
* we do? Unhook the old inode and hook up the new one?
*/
cmn_err(CE_PANIC,
"xfs_iget_core: ambiguous vns: vp/0x%p, invp/0x%p",
inode_vp, vp);
/*
* If lookup is racing with unlink, then we
* should return an error immediately so we
* don't remove it from the reclaim list and
* potentially leak the inode.
*/
if ((ip->i_d.di_mode == 0) &&
!(flags & XFS_IGET_CREATE)) {
read_unlock(&pag->pag_ici_lock);
xfs_put_perag(mp, pag);
return ENOENT;
}
/*
* Inode cache hit: if ip is not at the front of
* its hash chain, move it there now.
* Do this with the lock held for update, but
* do statistics after releasing the lock.
* There may be transactions sitting in the
* incore log buffers or being flushed to disk
* at this time. We can't clear the
* XFS_IRECLAIMABLE flag until these
* transactions have hit the disk, otherwise we
* will void the guarantee the flag provides
* xfs_iunpin()
*/
version = ih->ih_version;
read_unlock(&ih->ih_lock);
xfs_ihash_promote(ih, ip, version);
XFS_STATS_INC(xs_ig_found);
finish_inode:
if (ip->i_d.di_mode == 0) {
if (!(flags & XFS_IGET_CREATE))
return ENOENT;
xfs_iocore_inode_reinit(ip);
if (xfs_ipincount(ip)) {
read_unlock(&pag->pag_ici_lock);
xfs_log_force(mp, 0,
XFS_LOG_FORCE|XFS_LOG_SYNC);
XFS_STATS_INC(xs_ig_frecycle);
goto again;
}
if (lock_flags != 0)
xfs_ilock(ip, lock_flags);
vn_trace_exit(ip, "xfs_iget.alloc",
(inst_t *)__return_address);
xfs_iflags_clear(ip, XFS_ISTALE);
vn_trace_exit(vp, "xfs_iget.found",
(inst_t *)__return_address);
goto return_ip;
XFS_STATS_INC(xs_ig_found);
xfs_iflags_clear(ip, XFS_IRECLAIMABLE);
read_unlock(&pag->pag_ici_lock);
XFS_MOUNT_ILOCK(mp);
list_del_init(&ip->i_reclaim);
XFS_MOUNT_IUNLOCK(mp);
goto finish_inode;
} else if (vp != inode_vp) {
struct inode *inode = vn_to_inode(inode_vp);
/* The inode is being torn down, pause and
* try again.
*/
if (inode->i_state & (I_FREEING | I_CLEAR)) {
read_unlock(&pag->pag_ici_lock);
delay(1);
XFS_STATS_INC(xs_ig_frecycle);
goto again;
}
/* Chances are the other vnode (the one in the inode) is being torn
* down right now, and we landed on top of it. Question is, what do
* we do? Unhook the old inode and hook up the new one?
*/
cmn_err(CE_PANIC,
"xfs_iget_core: ambiguous vns: vp/0x%p, invp/0x%p",
inode_vp, vp);
}
/*
* Inode cache hit
*/
read_unlock(&pag->pag_ici_lock);
XFS_STATS_INC(xs_ig_found);
finish_inode:
if (ip->i_d.di_mode == 0) {
if (!(flags & XFS_IGET_CREATE)) {
xfs_put_perag(mp, pag);
return ENOENT;
}
xfs_iocore_inode_reinit(ip);
}
if (lock_flags != 0)
xfs_ilock(ip, lock_flags);
xfs_iflags_clear(ip, XFS_ISTALE);
vn_trace_exit(ip, "xfs_iget.found",
(inst_t *)__return_address);
goto return_ip;
}
/*
* Inode cache miss: save the hash chain version stamp and unlock
* the chain, so we don't deadlock in vn_alloc.
* Inode cache miss
*/
read_unlock(&pag->pag_ici_lock);
XFS_STATS_INC(xs_ig_missed);
version = ih->ih_version;
read_unlock(&ih->ih_lock);
/*
* Read the disk inode attributes into a new inode structure and get
* a new vnode for it. This should also initialize i_ino and i_mount.
*/
error = xfs_iread(mp, tp, ino, &ip, bno,
(flags & XFS_IGET_BULKSTAT) ? XFS_IMAP_BULKSTAT : 0);
if (error)
if (error) {
xfs_put_perag(mp, pag);
return error;
}
vn_trace_exit(vp, "xfs_iget.alloc", (inst_t *)__return_address);
vn_trace_exit(ip, "xfs_iget.alloc", (inst_t *)__return_address);
xfs_inode_lock_init(ip, vp);
xfs_iocore_inode_init(ip);
if (lock_flags)
xfs_ilock(ip, lock_flags);
if ((ip->i_d.di_mode == 0) && !(flags & XFS_IGET_CREATE)) {
xfs_idestroy(ip);
xfs_put_perag(mp, pag);
return ENOENT;
}
/*
* Put ip on its hash chain, unless someone else hashed a duplicate
* after we released the hash lock.
* This is a bit messy - we preallocate everything we _might_
* need before we pick up the ici lock. That way we don't have to
* juggle locks and go all the way back to the start.
*/
write_lock(&ih->ih_lock);
new_icl = kmem_zone_alloc(xfs_icluster_zone, KM_SLEEP);
if (radix_tree_preload(GFP_KERNEL)) {
delay(1);
goto again;
}
mask = ~(((XFS_INODE_CLUSTER_SIZE(mp) >> mp->m_sb.sb_inodelog)) - 1);
first_index = agino & mask;
write_lock(&pag->pag_ici_lock);
if (ih->ih_version != version) {
for (iq = ih->ih_next; iq != NULL; iq = iq->i_next) {
if (iq->i_ino == ino) {
write_unlock(&ih->ih_lock);
xfs_idestroy(ip);
/*
* Find the cluster if it exists
*/
icl = NULL;
if (radix_tree_gang_lookup(&pag->pag_ici_root, (void**)&iq,
first_index, 1)) {
if ((iq->i_ino & mask) == first_index)
icl = iq->i_cluster;
}
XFS_STATS_INC(xs_ig_dup);
goto again;
}
}
/*
* insert the new inode
*/
error = radix_tree_insert(&pag->pag_ici_root, agino, ip);
if (unlikely(error)) {
BUG_ON(error != -EEXIST);
write_unlock(&pag->pag_ici_lock);
radix_tree_preload_end();
xfs_idestroy(ip);
XFS_STATS_INC(xs_ig_dup);
goto again;
}
/*
* These values _must_ be set before releasing ihlock!
*/
ip->i_hash = ih;
if ((iq = ih->ih_next)) {
iq->i_prevp = &ip->i_next;
}
ip->i_next = iq;
ip->i_prevp = &ih->ih_next;
ih->ih_next = ip;
ip->i_udquot = ip->i_gdquot = NULL;
ih->ih_version++;
xfs_iflags_set(ip, XFS_INEW);
write_unlock(&ih->ih_lock);
/*
* put ip on its cluster's hash chain
*/
ASSERT(ip->i_chash == NULL && ip->i_cprev == NULL &&
ip->i_cnext == NULL);
ASSERT(ip->i_cluster == NULL);
chlnew = NULL;
ch = XFS_CHASH(mp, ip->i_blkno);
chlredo:
s = mutex_spinlock(&ch->ch_lock);
for (chl = ch->ch_list; chl != NULL; chl = chl->chl_next) {
if (chl->chl_blkno == ip->i_blkno) {
/* insert this inode into the doubly-linked list
* where chl points */
if ((iq = chl->chl_ip)) {
ip->i_cprev = iq->i_cprev;
iq->i_cprev->i_cnext = ip;
iq->i_cprev = ip;
ip->i_cnext = iq;
} else {
ip->i_cnext = ip;
ip->i_cprev = ip;
}
chl->chl_ip = ip;
ip->i_chash = chl;
break;
}
}
/* no hash list found for this block; add a new hash list */
if (chl == NULL) {
if (chlnew == NULL) {
mutex_spinunlock(&ch->ch_lock, s);
ASSERT(xfs_chashlist_zone != NULL);
chlnew = (xfs_chashlist_t *)
kmem_zone_alloc(xfs_chashlist_zone,
KM_SLEEP);
ASSERT(chlnew != NULL);
goto chlredo;
} else {
ip->i_cnext = ip;
ip->i_cprev = ip;
ip->i_chash = chlnew;
chlnew->chl_ip = ip;
chlnew->chl_blkno = ip->i_blkno;
if (ch->ch_list)
ch->ch_list->chl_prev = chlnew;
chlnew->chl_next = ch->ch_list;
chlnew->chl_prev = NULL;
ch->ch_list = chlnew;
chlnew = NULL;
}
if (!icl) {
spin_lock_init(&new_icl->icl_lock);
INIT_HLIST_HEAD(&new_icl->icl_inodes);
icl = new_icl;
new_icl = NULL;
} else {
if (chlnew != NULL) {
kmem_zone_free(xfs_chashlist_zone, chlnew);
}
ASSERT(!hlist_empty(&icl->icl_inodes));
}
spin_lock(&icl->icl_lock);
hlist_add_head(&ip->i_cnode, &icl->icl_inodes);
ip->i_cluster = icl;
spin_unlock(&icl->icl_lock);
mutex_spinunlock(&ch->ch_lock, s);
write_unlock(&pag->pag_ici_lock);
radix_tree_preload_end();
if (new_icl)
kmem_zone_free(xfs_icluster_zone, new_icl);
/*
* Link ip to its mount and thread it on the mount's inode list.
@ -478,6 +327,7 @@ finish_inode:
mp->m_inodes = ip;
XFS_MOUNT_IUNLOCK(mp);
xfs_put_perag(mp, pag);
return_ip:
ASSERT(ip->i_df.if_ext_max ==
@ -486,14 +336,14 @@ finish_inode:
ASSERT(((ip->i_d.di_flags & XFS_DIFLAG_REALTIME) != 0) ==
((ip->i_iocore.io_flags & XFS_IOCORE_RT) != 0));
xfs_iflags_set(ip, XFS_IMODIFIED);
*ipp = ip;
/*
* If we have a real type for an on-disk inode, we can set ops(&unlock)
* now. If it's a new inode being created, xfs_ialloc will handle it.
*/
bhv_vfs_init_vnode(XFS_MTOVFS(mp), vp, XFS_ITOBHV(ip), 1);
xfs_initialize_vnode(mp, vp, ip);
return 0;
}
@ -519,7 +369,8 @@ xfs_iget(
XFS_STATS_INC(xs_ig_attempts);
retry:
if ((inode = iget_locked(XFS_MTOVFS(mp)->vfs_super, ino))) {
inode = iget_locked(mp->m_super, ino);
if (inode) {
xfs_inode_t *ip;
vp = vn_from_inode(inode);
@ -570,8 +421,8 @@ xfs_inode_lock_init(
bhv_vnode_t *vp)
{
mrlock_init(&ip->i_lock, MRLOCK_ALLOW_EQUAL_PRI|MRLOCK_BARRIER,
"xfsino", (long)vp->v_number);
mrlock_init(&ip->i_iolock, MRLOCK_BARRIER, "xfsio", vp->v_number);
"xfsino", ip->i_ino);
mrlock_init(&ip->i_iolock, MRLOCK_BARRIER, "xfsio", ip->i_ino);
init_waitqueue_head(&ip->i_ipin_wait);
atomic_set(&ip->i_pincount, 0);
initnsema(&ip->i_flock, 1, "xfsfino");
@ -587,32 +438,19 @@ xfs_inode_incore(xfs_mount_t *mp,
xfs_ino_t ino,
xfs_trans_t *tp)
{
xfs_ihash_t *ih;
xfs_inode_t *ip;
ulong version;
xfs_perag_t *pag;
ih = XFS_IHASH(mp, ino);
read_lock(&ih->ih_lock);
for (ip = ih->ih_next; ip != NULL; ip = ip->i_next) {
if (ip->i_ino == ino) {
/*
* If we find it and tp matches, return it.
* Also move it to the front of the hash list
* if we find it and it is not already there.
* Otherwise break from the loop and return
* NULL.
*/
if (ip->i_transp == tp) {
version = ih->ih_version;
read_unlock(&ih->ih_lock);
xfs_ihash_promote(ih, ip, version);
return (ip);
}
break;
}
}
read_unlock(&ih->ih_lock);
return (NULL);
pag = xfs_get_perag(mp, ino);
read_lock(&pag->pag_ici_lock);
ip = radix_tree_lookup(&pag->pag_ici_root, XFS_INO_TO_AGINO(mp, ino));
read_unlock(&pag->pag_ici_lock);
xfs_put_perag(mp, pag);
/* the returned inode must match the transaction */
if (ip && (ip->i_transp != tp))
return NULL;
return ip;
}
/*
@ -629,7 +467,7 @@ xfs_iput(xfs_inode_t *ip,
{
bhv_vnode_t *vp = XFS_ITOV(ip);
vn_trace_entry(vp, "xfs_iput", (inst_t *)__return_address);
vn_trace_entry(ip, "xfs_iput", (inst_t *)__return_address);
xfs_iunlock(ip, lock_flags);
VN_RELE(vp);
}
@ -644,7 +482,7 @@ xfs_iput_new(xfs_inode_t *ip,
bhv_vnode_t *vp = XFS_ITOV(ip);
struct inode *inode = vn_to_inode(vp);
vn_trace_entry(vp, "xfs_iput_new", (inst_t *)__return_address);
vn_trace_entry(ip, "xfs_iput_new", (inst_t *)__return_address);
if ((ip->i_d.di_mode == 0)) {
ASSERT(!xfs_iflags_test(ip, XFS_IRECLAIMABLE));
@ -699,7 +537,8 @@ xfs_ireclaim(xfs_inode_t *ip)
*/
vp = XFS_ITOV_NULL(ip);
if (vp) {
vn_bhv_remove(VN_BHV_HEAD(vp), XFS_ITOBHV(ip));
vn_to_inode(vp)->i_private = NULL;
ip->i_vnode = NULL;
}
/*
@ -718,58 +557,26 @@ void
xfs_iextract(
xfs_inode_t *ip)
{
xfs_ihash_t *ih;
xfs_mount_t *mp = ip->i_mount;
xfs_perag_t *pag = xfs_get_perag(mp, ip->i_ino);
xfs_inode_t *iq;
xfs_mount_t *mp;
xfs_chash_t *ch;
xfs_chashlist_t *chl, *chm;
SPLDECL(s);
ih = ip->i_hash;
write_lock(&ih->ih_lock);
if ((iq = ip->i_next)) {
iq->i_prevp = ip->i_prevp;
}
*ip->i_prevp = iq;
ih->ih_version++;
write_unlock(&ih->ih_lock);
write_lock(&pag->pag_ici_lock);
radix_tree_delete(&pag->pag_ici_root, XFS_INO_TO_AGINO(mp, ip->i_ino));
write_unlock(&pag->pag_ici_lock);
xfs_put_perag(mp, pag);
/*
* Remove from cluster hash list
* 1) delete the chashlist if this is the last inode on the chashlist
* 2) unchain from list of inodes
* 3) point chashlist->chl_ip to 'chl_next' if to this inode.
* Remove from cluster list
*/
mp = ip->i_mount;
ch = XFS_CHASH(mp, ip->i_blkno);
s = mutex_spinlock(&ch->ch_lock);
spin_lock(&ip->i_cluster->icl_lock);
hlist_del(&ip->i_cnode);
spin_unlock(&ip->i_cluster->icl_lock);
if (ip->i_cnext == ip) {
/* Last inode on chashlist */
ASSERT(ip->i_cnext == ip && ip->i_cprev == ip);
ASSERT(ip->i_chash != NULL);
chm=NULL;
chl = ip->i_chash;
if (chl->chl_prev)
chl->chl_prev->chl_next = chl->chl_next;
else
ch->ch_list = chl->chl_next;
if (chl->chl_next)
chl->chl_next->chl_prev = chl->chl_prev;
kmem_zone_free(xfs_chashlist_zone, chl);
} else {
/* delete one inode from a non-empty list */
iq = ip->i_cnext;
iq->i_cprev = ip->i_cprev;
ip->i_cprev->i_cnext = iq;
if (ip->i_chash->chl_ip == ip) {
ip->i_chash->chl_ip = iq;
}
ip->i_chash = __return_address;
ip->i_cprev = __return_address;
ip->i_cnext = __return_address;
}
mutex_spinunlock(&ch->ch_lock, s);
/* was last inode in cluster? */
if (hlist_empty(&ip->i_cluster->icl_inodes))
kmem_zone_free(xfs_icluster_zone, ip->i_cluster);
/*
* Remove from mount's inode list.

View file

@ -49,12 +49,11 @@
#include "xfs_quota.h"
#include "xfs_acl.h"
#include "xfs_filestream.h"
#include <linux/log2.h>
#include "xfs_vnodeops.h"
kmem_zone_t *xfs_ifork_zone;
kmem_zone_t *xfs_inode_zone;
kmem_zone_t *xfs_chashlist_zone;
kmem_zone_t *xfs_icluster_zone;
/*
* Used in xfs_itruncate(). This is the maximum number of extents
@ -67,7 +66,6 @@ STATIC int xfs_iformat_local(xfs_inode_t *, xfs_dinode_t *, int, int);
STATIC int xfs_iformat_extents(xfs_inode_t *, xfs_dinode_t *, int);
STATIC int xfs_iformat_btree(xfs_inode_t *, xfs_dinode_t *, int);
#ifdef DEBUG
/*
* Make sure that the extents in the given memory buffer
@ -77,28 +75,23 @@ STATIC void
xfs_validate_extents(
xfs_ifork_t *ifp,
int nrecs,
int disk,
xfs_exntfmt_t fmt)
{
xfs_bmbt_rec_t *ep;
xfs_bmbt_irec_t irec;
xfs_bmbt_rec_t rec;
xfs_bmbt_rec_host_t rec;
int i;
for (i = 0; i < nrecs; i++) {
ep = xfs_iext_get_ext(ifp, i);
rec.l0 = get_unaligned((__uint64_t*)&ep->l0);
rec.l1 = get_unaligned((__uint64_t*)&ep->l1);
if (disk)
xfs_bmbt_disk_get_all(&rec, &irec);
else
xfs_bmbt_get_all(&rec, &irec);
xfs_bmbt_rec_host_t *ep = xfs_iext_get_ext(ifp, i);
rec.l0 = get_unaligned(&ep->l0);
rec.l1 = get_unaligned(&ep->l1);
xfs_bmbt_get_all(&rec, &irec);
if (fmt == XFS_EXTFMT_NOSTATE)
ASSERT(irec.br_state == XFS_EXT_NORM);
}
}
#else /* DEBUG */
#define xfs_validate_extents(ifp, nrecs, disk, fmt)
#define xfs_validate_extents(ifp, nrecs, fmt)
#endif /* DEBUG */
/*
@ -201,8 +194,8 @@ xfs_inotobp(
}
dip = (xfs_dinode_t *)xfs_buf_offset(bp, 0);
di_ok =
INT_GET(dip->di_core.di_magic, ARCH_CONVERT) == XFS_DINODE_MAGIC &&
XFS_DINODE_GOOD_VERSION(INT_GET(dip->di_core.di_version, ARCH_CONVERT));
be16_to_cpu(dip->di_core.di_magic) == XFS_DINODE_MAGIC &&
XFS_DINODE_GOOD_VERSION(dip->di_core.di_version);
if (unlikely(XFS_TEST_ERROR(!di_ok, mp, XFS_ERRTAG_ITOBP_INOTOBP,
XFS_RANDOM_ITOBP_INOTOBP))) {
XFS_CORRUPTION_ERROR("xfs_inotobp", XFS_ERRLEVEL_LOW, mp, dip);
@ -346,8 +339,8 @@ xfs_itobp(
dip = (xfs_dinode_t *)xfs_buf_offset(bp,
(i << mp->m_sb.sb_inodelog));
di_ok = INT_GET(dip->di_core.di_magic, ARCH_CONVERT) == XFS_DINODE_MAGIC &&
XFS_DINODE_GOOD_VERSION(INT_GET(dip->di_core.di_version, ARCH_CONVERT));
di_ok = be16_to_cpu(dip->di_core.di_magic) == XFS_DINODE_MAGIC &&
XFS_DINODE_GOOD_VERSION(dip->di_core.di_version);
if (unlikely(XFS_TEST_ERROR(!di_ok, mp,
XFS_ERRTAG_ITOBP_INOTOBP,
XFS_RANDOM_ITOBP_INOTOBP))) {
@ -361,7 +354,7 @@ xfs_itobp(
"daddr %lld #%d (magic=%x)",
XFS_BUFTARG_NAME(mp->m_ddev_targp),
(unsigned long long)imap.im_blkno, i,
INT_GET(dip->di_core.di_magic, ARCH_CONVERT));
be16_to_cpu(dip->di_core.di_magic));
#endif
XFS_CORRUPTION_ERROR("xfs_itobp", XFS_ERRLEVEL_HIGH,
mp, dip);
@ -407,27 +400,26 @@ xfs_iformat(
XFS_IFORK_DSIZE(ip) / (uint)sizeof(xfs_bmbt_rec_t);
error = 0;
if (unlikely(
INT_GET(dip->di_core.di_nextents, ARCH_CONVERT) +
INT_GET(dip->di_core.di_anextents, ARCH_CONVERT) >
INT_GET(dip->di_core.di_nblocks, ARCH_CONVERT))) {
if (unlikely(be32_to_cpu(dip->di_core.di_nextents) +
be16_to_cpu(dip->di_core.di_anextents) >
be64_to_cpu(dip->di_core.di_nblocks))) {
xfs_fs_repair_cmn_err(CE_WARN, ip->i_mount,
"corrupt dinode %Lu, extent total = %d, nblocks = %Lu.",
(unsigned long long)ip->i_ino,
(int)(INT_GET(dip->di_core.di_nextents, ARCH_CONVERT)
+ INT_GET(dip->di_core.di_anextents, ARCH_CONVERT)),
(int)(be32_to_cpu(dip->di_core.di_nextents) +
be16_to_cpu(dip->di_core.di_anextents)),
(unsigned long long)
INT_GET(dip->di_core.di_nblocks, ARCH_CONVERT));
be64_to_cpu(dip->di_core.di_nblocks));
XFS_CORRUPTION_ERROR("xfs_iformat(1)", XFS_ERRLEVEL_LOW,
ip->i_mount, dip);
return XFS_ERROR(EFSCORRUPTED);
}
if (unlikely(INT_GET(dip->di_core.di_forkoff, ARCH_CONVERT) > ip->i_mount->m_sb.sb_inodesize)) {
if (unlikely(dip->di_core.di_forkoff > ip->i_mount->m_sb.sb_inodesize)) {
xfs_fs_repair_cmn_err(CE_WARN, ip->i_mount,
"corrupt dinode %Lu, forkoff = 0x%x.",
(unsigned long long)ip->i_ino,
(int)(INT_GET(dip->di_core.di_forkoff, ARCH_CONVERT)));
dip->di_core.di_forkoff);
XFS_CORRUPTION_ERROR("xfs_iformat(2)", XFS_ERRLEVEL_LOW,
ip->i_mount, dip);
return XFS_ERROR(EFSCORRUPTED);
@ -438,25 +430,25 @@ xfs_iformat(
case S_IFCHR:
case S_IFBLK:
case S_IFSOCK:
if (unlikely(INT_GET(dip->di_core.di_format, ARCH_CONVERT) != XFS_DINODE_FMT_DEV)) {
if (unlikely(dip->di_core.di_format != XFS_DINODE_FMT_DEV)) {
XFS_CORRUPTION_ERROR("xfs_iformat(3)", XFS_ERRLEVEL_LOW,
ip->i_mount, dip);
return XFS_ERROR(EFSCORRUPTED);
}
ip->i_d.di_size = 0;
ip->i_size = 0;
ip->i_df.if_u2.if_rdev = INT_GET(dip->di_u.di_dev, ARCH_CONVERT);
ip->i_df.if_u2.if_rdev = be32_to_cpu(dip->di_u.di_dev);
break;
case S_IFREG:
case S_IFLNK:
case S_IFDIR:
switch (INT_GET(dip->di_core.di_format, ARCH_CONVERT)) {
switch (dip->di_core.di_format) {
case XFS_DINODE_FMT_LOCAL:
/*
* no local regular files yet
*/
if (unlikely((INT_GET(dip->di_core.di_mode, ARCH_CONVERT) & S_IFMT) == S_IFREG)) {
if (unlikely((be16_to_cpu(dip->di_core.di_mode) & S_IFMT) == S_IFREG)) {
xfs_fs_repair_cmn_err(CE_WARN, ip->i_mount,
"corrupt inode %Lu "
"(local format for regular file).",
@ -467,7 +459,7 @@ xfs_iformat(
return XFS_ERROR(EFSCORRUPTED);
}
di_size = INT_GET(dip->di_core.di_size, ARCH_CONVERT);
di_size = be64_to_cpu(dip->di_core.di_size);
if (unlikely(di_size > XFS_DFORK_DSIZE(dip, ip->i_mount))) {
xfs_fs_repair_cmn_err(CE_WARN, ip->i_mount,
"corrupt inode %Lu "
@ -509,7 +501,7 @@ xfs_iformat(
ip->i_afp = kmem_zone_zalloc(xfs_ifork_zone, KM_SLEEP);
ip->i_afp->if_ext_max =
XFS_IFORK_ASIZE(ip) / (uint)sizeof(xfs_bmbt_rec_t);
switch (INT_GET(dip->di_core.di_aformat, ARCH_CONVERT)) {
switch (dip->di_core.di_aformat) {
case XFS_DINODE_FMT_LOCAL:
atp = (xfs_attr_shortform_t *)XFS_DFORK_APTR(dip);
size = be16_to_cpu(atp->hdr.totsize);
@ -602,7 +594,7 @@ xfs_iformat_extents(
xfs_dinode_t *dip,
int whichfork)
{
xfs_bmbt_rec_t *ep, *dp;
xfs_bmbt_rec_t *dp;
xfs_ifork_t *ifp;
int nex;
int size;
@ -637,13 +629,11 @@ xfs_iformat_extents(
ifp->if_bytes = size;
if (size) {
dp = (xfs_bmbt_rec_t *) XFS_DFORK_PTR(dip, whichfork);
xfs_validate_extents(ifp, nex, 1, XFS_EXTFMT_INODE(ip));
xfs_validate_extents(ifp, nex, XFS_EXTFMT_INODE(ip));
for (i = 0; i < nex; i++, dp++) {
ep = xfs_iext_get_ext(ifp, i);
ep->l0 = INT_GET(get_unaligned((__uint64_t*)&dp->l0),
ARCH_CONVERT);
ep->l1 = INT_GET(get_unaligned((__uint64_t*)&dp->l1),
ARCH_CONVERT);
xfs_bmbt_rec_host_t *ep = xfs_iext_get_ext(ifp, i);
ep->l0 = be64_to_cpu(get_unaligned(&dp->l0));
ep->l1 = be64_to_cpu(get_unaligned(&dp->l1));
}
XFS_BMAP_TRACE_EXLIST(ip, nex, whichfork);
if (whichfork != XFS_DATA_FORK ||
@ -719,70 +709,74 @@ xfs_iformat_btree(
return 0;
}
/*
* xfs_xlate_dinode_core - translate an xfs_inode_core_t between ondisk
* and native format
*
* buf = on-disk representation
* dip = native representation
* dir = direction - +ve -> disk to native
* -ve -> native to disk
*/
void
xfs_xlate_dinode_core(
xfs_caddr_t buf,
xfs_dinode_core_t *dip,
int dir)
xfs_dinode_from_disk(
xfs_icdinode_t *to,
xfs_dinode_core_t *from)
{
xfs_dinode_core_t *buf_core = (xfs_dinode_core_t *)buf;
xfs_dinode_core_t *mem_core = (xfs_dinode_core_t *)dip;
xfs_arch_t arch = ARCH_CONVERT;
to->di_magic = be16_to_cpu(from->di_magic);
to->di_mode = be16_to_cpu(from->di_mode);
to->di_version = from ->di_version;
to->di_format = from->di_format;
to->di_onlink = be16_to_cpu(from->di_onlink);
to->di_uid = be32_to_cpu(from->di_uid);
to->di_gid = be32_to_cpu(from->di_gid);
to->di_nlink = be32_to_cpu(from->di_nlink);
to->di_projid = be16_to_cpu(from->di_projid);
memcpy(to->di_pad, from->di_pad, sizeof(to->di_pad));
to->di_flushiter = be16_to_cpu(from->di_flushiter);
to->di_atime.t_sec = be32_to_cpu(from->di_atime.t_sec);
to->di_atime.t_nsec = be32_to_cpu(from->di_atime.t_nsec);
to->di_mtime.t_sec = be32_to_cpu(from->di_mtime.t_sec);
to->di_mtime.t_nsec = be32_to_cpu(from->di_mtime.t_nsec);
to->di_ctime.t_sec = be32_to_cpu(from->di_ctime.t_sec);
to->di_ctime.t_nsec = be32_to_cpu(from->di_ctime.t_nsec);
to->di_size = be64_to_cpu(from->di_size);
to->di_nblocks = be64_to_cpu(from->di_nblocks);
to->di_extsize = be32_to_cpu(from->di_extsize);
to->di_nextents = be32_to_cpu(from->di_nextents);
to->di_anextents = be16_to_cpu(from->di_anextents);
to->di_forkoff = from->di_forkoff;
to->di_aformat = from->di_aformat;
to->di_dmevmask = be32_to_cpu(from->di_dmevmask);
to->di_dmstate = be16_to_cpu(from->di_dmstate);
to->di_flags = be16_to_cpu(from->di_flags);
to->di_gen = be32_to_cpu(from->di_gen);
}
ASSERT(dir);
INT_XLATE(buf_core->di_magic, mem_core->di_magic, dir, arch);
INT_XLATE(buf_core->di_mode, mem_core->di_mode, dir, arch);
INT_XLATE(buf_core->di_version, mem_core->di_version, dir, arch);
INT_XLATE(buf_core->di_format, mem_core->di_format, dir, arch);
INT_XLATE(buf_core->di_onlink, mem_core->di_onlink, dir, arch);
INT_XLATE(buf_core->di_uid, mem_core->di_uid, dir, arch);
INT_XLATE(buf_core->di_gid, mem_core->di_gid, dir, arch);
INT_XLATE(buf_core->di_nlink, mem_core->di_nlink, dir, arch);
INT_XLATE(buf_core->di_projid, mem_core->di_projid, dir, arch);
if (dir > 0) {
memcpy(mem_core->di_pad, buf_core->di_pad,
sizeof(buf_core->di_pad));
} else {
memcpy(buf_core->di_pad, mem_core->di_pad,
sizeof(buf_core->di_pad));
}
INT_XLATE(buf_core->di_flushiter, mem_core->di_flushiter, dir, arch);
INT_XLATE(buf_core->di_atime.t_sec, mem_core->di_atime.t_sec,
dir, arch);
INT_XLATE(buf_core->di_atime.t_nsec, mem_core->di_atime.t_nsec,
dir, arch);
INT_XLATE(buf_core->di_mtime.t_sec, mem_core->di_mtime.t_sec,
dir, arch);
INT_XLATE(buf_core->di_mtime.t_nsec, mem_core->di_mtime.t_nsec,
dir, arch);
INT_XLATE(buf_core->di_ctime.t_sec, mem_core->di_ctime.t_sec,
dir, arch);
INT_XLATE(buf_core->di_ctime.t_nsec, mem_core->di_ctime.t_nsec,
dir, arch);
INT_XLATE(buf_core->di_size, mem_core->di_size, dir, arch);
INT_XLATE(buf_core->di_nblocks, mem_core->di_nblocks, dir, arch);
INT_XLATE(buf_core->di_extsize, mem_core->di_extsize, dir, arch);
INT_XLATE(buf_core->di_nextents, mem_core->di_nextents, dir, arch);
INT_XLATE(buf_core->di_anextents, mem_core->di_anextents, dir, arch);
INT_XLATE(buf_core->di_forkoff, mem_core->di_forkoff, dir, arch);
INT_XLATE(buf_core->di_aformat, mem_core->di_aformat, dir, arch);
INT_XLATE(buf_core->di_dmevmask, mem_core->di_dmevmask, dir, arch);
INT_XLATE(buf_core->di_dmstate, mem_core->di_dmstate, dir, arch);
INT_XLATE(buf_core->di_flags, mem_core->di_flags, dir, arch);
INT_XLATE(buf_core->di_gen, mem_core->di_gen, dir, arch);
void
xfs_dinode_to_disk(
xfs_dinode_core_t *to,
xfs_icdinode_t *from)
{
to->di_magic = cpu_to_be16(from->di_magic);
to->di_mode = cpu_to_be16(from->di_mode);
to->di_version = from ->di_version;
to->di_format = from->di_format;
to->di_onlink = cpu_to_be16(from->di_onlink);
to->di_uid = cpu_to_be32(from->di_uid);
to->di_gid = cpu_to_be32(from->di_gid);
to->di_nlink = cpu_to_be32(from->di_nlink);
to->di_projid = cpu_to_be16(from->di_projid);
memcpy(to->di_pad, from->di_pad, sizeof(to->di_pad));
to->di_flushiter = cpu_to_be16(from->di_flushiter);
to->di_atime.t_sec = cpu_to_be32(from->di_atime.t_sec);
to->di_atime.t_nsec = cpu_to_be32(from->di_atime.t_nsec);
to->di_mtime.t_sec = cpu_to_be32(from->di_mtime.t_sec);
to->di_mtime.t_nsec = cpu_to_be32(from->di_mtime.t_nsec);
to->di_ctime.t_sec = cpu_to_be32(from->di_ctime.t_sec);
to->di_ctime.t_nsec = cpu_to_be32(from->di_ctime.t_nsec);
to->di_size = cpu_to_be64(from->di_size);
to->di_nblocks = cpu_to_be64(from->di_nblocks);
to->di_extsize = cpu_to_be32(from->di_extsize);
to->di_nextents = cpu_to_be32(from->di_nextents);
to->di_anextents = cpu_to_be16(from->di_anextents);
to->di_forkoff = from->di_forkoff;
to->di_aformat = from->di_aformat;
to->di_dmevmask = cpu_to_be32(from->di_dmevmask);
to->di_dmstate = cpu_to_be16(from->di_dmstate);
to->di_flags = cpu_to_be16(from->di_flags);
to->di_gen = cpu_to_be32(from->di_gen);
}
STATIC uint
@ -829,7 +823,7 @@ uint
xfs_ip2xflags(
xfs_inode_t *ip)
{
xfs_dinode_core_t *dic = &ip->i_d;
xfs_icdinode_t *dic = &ip->i_d;
return _xfs_dic2xflags(dic->di_flags) |
(XFS_CFORK_Q(dic) ? XFS_XFLAG_HASATTR : 0);
@ -839,7 +833,7 @@ uint
xfs_dic2xflags(
xfs_dinode_core_t *dic)
{
return _xfs_dic2xflags(INT_GET(dic->di_flags, ARCH_CONVERT)) |
return _xfs_dic2xflags(be16_to_cpu(dic->di_flags)) |
(XFS_CFORK_Q_DISK(dic) ? XFS_XFLAG_HASATTR : 0);
}
@ -870,6 +864,7 @@ xfs_iread(
ip = kmem_zone_zalloc(xfs_inode_zone, KM_SLEEP);
ip->i_ino = ino;
ip->i_mount = mp;
atomic_set(&ip->i_iocount, 0);
spin_lock_init(&ip->i_flags_lock);
/*
@ -889,6 +884,9 @@ xfs_iread(
* Initialize inode's trace buffers.
* Do this before xfs_iformat in case it adds entries.
*/
#ifdef XFS_VNODE_TRACE
ip->i_trace = ktrace_alloc(VNODE_TRACE_SIZE, KM_SLEEP);
#endif
#ifdef XFS_BMAP_TRACE
ip->i_xtrace = ktrace_alloc(XFS_BMAP_KTRACE_SIZE, KM_SLEEP);
#endif
@ -909,14 +907,14 @@ xfs_iread(
* If we got something that isn't an inode it means someone
* (nfs or dmi) has a stale handle.
*/
if (INT_GET(dip->di_core.di_magic, ARCH_CONVERT) != XFS_DINODE_MAGIC) {
if (be16_to_cpu(dip->di_core.di_magic) != XFS_DINODE_MAGIC) {
kmem_zone_free(xfs_inode_zone, ip);
xfs_trans_brelse(tp, bp);
#ifdef DEBUG
xfs_fs_cmn_err(CE_ALERT, mp, "xfs_iread: "
"dip->di_core.di_magic (0x%x) != "
"XFS_DINODE_MAGIC (0x%x)",
INT_GET(dip->di_core.di_magic, ARCH_CONVERT),
be16_to_cpu(dip->di_core.di_magic),
XFS_DINODE_MAGIC);
#endif /* DEBUG */
return XFS_ERROR(EINVAL);
@ -930,8 +928,7 @@ xfs_iread(
* Otherwise, just get the truly permanent information.
*/
if (dip->di_core.di_mode) {
xfs_xlate_dinode_core((xfs_caddr_t)&dip->di_core,
&(ip->i_d), 1);
xfs_dinode_from_disk(&ip->i_d, &dip->di_core);
error = xfs_iformat(ip, dip);
if (error) {
kmem_zone_free(xfs_inode_zone, ip);
@ -944,10 +941,10 @@ xfs_iread(
return error;
}
} else {
ip->i_d.di_magic = INT_GET(dip->di_core.di_magic, ARCH_CONVERT);
ip->i_d.di_version = INT_GET(dip->di_core.di_version, ARCH_CONVERT);
ip->i_d.di_gen = INT_GET(dip->di_core.di_gen, ARCH_CONVERT);
ip->i_d.di_flushiter = INT_GET(dip->di_core.di_flushiter, ARCH_CONVERT);
ip->i_d.di_magic = be16_to_cpu(dip->di_core.di_magic);
ip->i_d.di_version = dip->di_core.di_version;
ip->i_d.di_gen = be32_to_cpu(dip->di_core.di_gen);
ip->i_d.di_flushiter = be16_to_cpu(dip->di_core.di_flushiter);
/*
* Make sure to pull in the mode here as well in
* case the inode is released without being used.
@ -1048,7 +1045,7 @@ xfs_iread_extents(
ifp->if_flags &= ~XFS_IFEXTENTS;
return error;
}
xfs_validate_extents(ifp, nextents, 0, XFS_EXTFMT_INODE(ip));
xfs_validate_extents(ifp, nextents, XFS_EXTFMT_INODE(ip));
return 0;
}
@ -1161,7 +1158,7 @@ xfs_ialloc(
if ((prid != 0) && (ip->i_d.di_version == XFS_DINODE_VERSION_1))
xfs_bump_ino_vers2(tp, ip);
if (pip && XFS_INHERIT_GID(pip, vp->v_vfsp)) {
if (pip && XFS_INHERIT_GID(pip)) {
ip->i_d.di_gid = pip->i_d.di_gid;
if ((pip->i_d.di_mode & S_ISGID) && (mode & S_IFMT) == S_IFDIR) {
ip->i_d.di_mode |= S_ISGID;
@ -1275,7 +1272,7 @@ xfs_ialloc(
xfs_trans_log_inode(tp, ip, flags);
/* now that we have an i_mode we can setup inode ops and unlock */
bhv_vfs_init_vnode(XFS_MTOVFS(tp->t_mountp), vp, XFS_ITOBHV(ip), 1);
xfs_initialize_vnode(tp->t_mountp, vp, ip);
*ipp = ip;
return 0;
@ -1462,7 +1459,7 @@ xfs_itruncate_start(
mp = ip->i_mount;
vp = XFS_ITOV(ip);
vn_iowait(vp); /* wait for the completion of any pending DIOs */
vn_iowait(ip); /* wait for the completion of any pending DIOs */
/*
* Call toss_pages or flushinval_pages to get rid of pages
@ -1497,9 +1494,11 @@ xfs_itruncate_start(
last_byte);
if (last_byte > toss_start) {
if (flags & XFS_ITRUNC_DEFINITE) {
bhv_vop_toss_pages(vp, toss_start, -1, FI_REMAPF_LOCKED);
xfs_tosspages(ip, toss_start,
-1, FI_REMAPF_LOCKED);
} else {
error = bhv_vop_flushinval_pages(vp, toss_start, -1, FI_REMAPF_LOCKED);
error = xfs_flushinval_pages(ip, toss_start,
-1, FI_REMAPF_LOCKED);
}
}
@ -1932,9 +1931,9 @@ xfs_iunlink(
*/
error = xfs_trans_read_buf(mp, tp, mp->m_ddev_targp, agdaddr,
XFS_FSS_TO_BB(mp, 1), 0, &agibp);
if (error) {
if (error)
return error;
}
/*
* Validate the magic number of the agi block.
*/
@ -1958,6 +1957,24 @@ xfs_iunlink(
ASSERT(agi->agi_unlinked[bucket_index]);
ASSERT(be32_to_cpu(agi->agi_unlinked[bucket_index]) != agino);
error = xfs_itobp(mp, tp, ip, &dip, &ibp, 0, 0);
if (error)
return error;
/*
* Clear the on-disk di_nlink. This is to prevent xfs_bulkstat
* from picking up this inode when it is reclaimed (its incore state
* initialzed but not flushed to disk yet). The in-core di_nlink is
* already cleared in xfs_droplink() and a corresponding transaction
* logged. The hack here just synchronizes the in-core to on-disk
* di_nlink value in advance before the actual inode sync to disk.
* This is OK because the inode is already unlinked and would never
* change its di_nlink again for this inode generation.
* This is a temporary hack that would require a proper fix
* in the future.
*/
dip->di_core.di_nlink = 0;
if (be32_to_cpu(agi->agi_unlinked[bucket_index]) != NULLAGINO) {
/*
* There is already another inode in the bucket we need
@ -1965,12 +1982,7 @@ xfs_iunlink(
* Here we put the head pointer into our next pointer,
* and then we fall through to point the head at us.
*/
error = xfs_itobp(mp, tp, ip, &dip, &ibp, 0, 0);
if (error) {
return error;
}
ASSERT(INT_GET(dip->di_next_unlinked, ARCH_CONVERT) == NULLAGINO);
ASSERT(dip->di_next_unlinked);
ASSERT(be32_to_cpu(dip->di_next_unlinked) == NULLAGINO);
/* both on-disk, don't endian flip twice */
dip->di_next_unlinked = agi->agi_unlinked[bucket_index];
offset = ip->i_boffset +
@ -2081,10 +2093,10 @@ xfs_iunlink_remove(
error, mp->m_fsname);
return error;
}
next_agino = INT_GET(dip->di_next_unlinked, ARCH_CONVERT);
next_agino = be32_to_cpu(dip->di_next_unlinked);
ASSERT(next_agino != 0);
if (next_agino != NULLAGINO) {
INT_SET(dip->di_next_unlinked, ARCH_CONVERT, NULLAGINO);
dip->di_next_unlinked = cpu_to_be32(NULLAGINO);
offset = ip->i_boffset +
offsetof(xfs_dinode_t, di_next_unlinked);
xfs_trans_inode_buf(tp, ibp);
@ -2128,7 +2140,7 @@ xfs_iunlink_remove(
error, mp->m_fsname);
return error;
}
next_agino = INT_GET(last_dip->di_next_unlinked, ARCH_CONVERT);
next_agino = be32_to_cpu(last_dip->di_next_unlinked);
ASSERT(next_agino != NULLAGINO);
ASSERT(next_agino != 0);
}
@ -2143,11 +2155,11 @@ xfs_iunlink_remove(
error, mp->m_fsname);
return error;
}
next_agino = INT_GET(dip->di_next_unlinked, ARCH_CONVERT);
next_agino = be32_to_cpu(dip->di_next_unlinked);
ASSERT(next_agino != 0);
ASSERT(next_agino != agino);
if (next_agino != NULLAGINO) {
INT_SET(dip->di_next_unlinked, ARCH_CONVERT, NULLAGINO);
dip->di_next_unlinked = cpu_to_be32(NULLAGINO);
offset = ip->i_boffset +
offsetof(xfs_dinode_t, di_next_unlinked);
xfs_trans_inode_buf(tp, ibp);
@ -2160,7 +2172,7 @@ xfs_iunlink_remove(
/*
* Point the previous inode on the list to the next inode.
*/
INT_SET(last_dip->di_next_unlinked, ARCH_CONVERT, next_agino);
last_dip->di_next_unlinked = cpu_to_be32(next_agino);
ASSERT(next_agino != 0);
offset = last_offset + offsetof(xfs_dinode_t, di_next_unlinked);
xfs_trans_inode_buf(tp, last_ibp);
@ -2191,10 +2203,10 @@ xfs_ifree_cluster(
int i, j, found, pre_flushed;
xfs_daddr_t blkno;
xfs_buf_t *bp;
xfs_ihash_t *ih;
xfs_inode_t *ip, **ip_found;
xfs_inode_log_item_t *iip;
xfs_log_item_t *lip;
xfs_perag_t *pag = xfs_get_perag(mp, inum);
SPLDECL(s);
if (mp->m_sb.sb_blocksize >= XFS_INODE_CLUSTER_SIZE(mp)) {
@ -2229,23 +2241,20 @@ xfs_ifree_cluster(
*/
found = 0;
for (i = 0; i < ninodes; i++) {
ih = XFS_IHASH(mp, inum + i);
read_lock(&ih->ih_lock);
for (ip = ih->ih_next; ip != NULL; ip = ip->i_next) {
if (ip->i_ino == inum + i)
break;
}
read_lock(&pag->pag_ici_lock);
ip = radix_tree_lookup(&pag->pag_ici_root,
XFS_INO_TO_AGINO(mp, (inum + i)));
/* Inode not in memory or we found it already,
* nothing to do
*/
if (!ip || xfs_iflags_test(ip, XFS_ISTALE)) {
read_unlock(&ih->ih_lock);
read_unlock(&pag->pag_ici_lock);
continue;
}
if (xfs_inode_clean(ip)) {
read_unlock(&ih->ih_lock);
read_unlock(&pag->pag_ici_lock);
continue;
}
@ -2268,7 +2277,7 @@ xfs_ifree_cluster(
ip_found[found++] = ip;
}
}
read_unlock(&ih->ih_lock);
read_unlock(&pag->pag_ici_lock);
continue;
}
@ -2286,8 +2295,7 @@ xfs_ifree_cluster(
xfs_iunlock(ip, XFS_ILOCK_EXCL);
}
}
read_unlock(&ih->ih_lock);
read_unlock(&pag->pag_ici_lock);
}
bp = xfs_trans_get_buf(tp, mp->m_ddev_targp, blkno,
@ -2342,6 +2350,7 @@ xfs_ifree_cluster(
}
kmem_free(ip_found, ninodes * sizeof(xfs_inode_t *));
xfs_put_perag(mp, pag);
}
/*
@ -2737,6 +2746,10 @@ xfs_idestroy(
mrfree(&ip->i_lock);
mrfree(&ip->i_iolock);
freesema(&ip->i_flock);
#ifdef XFS_VNODE_TRACE
ktrace_free(ip->i_trace);
#endif
#ifdef XFS_BMAP_TRACE
ktrace_free(ip->i_xtrace);
#endif
@ -2887,12 +2900,10 @@ xfs_iunpin_wait(
int
xfs_iextents_copy(
xfs_inode_t *ip,
xfs_bmbt_rec_t *buffer,
xfs_bmbt_rec_t *dp,
int whichfork)
{
int copied;
xfs_bmbt_rec_t *dest_ep;
xfs_bmbt_rec_t *ep;
int i;
xfs_ifork_t *ifp;
int nrecs;
@ -2912,10 +2923,9 @@ xfs_iextents_copy(
* the delayed ones. There must be at least one
* non-delayed extent.
*/
dest_ep = buffer;
copied = 0;
for (i = 0; i < nrecs; i++) {
ep = xfs_iext_get_ext(ifp, i);
xfs_bmbt_rec_host_t *ep = xfs_iext_get_ext(ifp, i);
start_block = xfs_bmbt_get_startblock(ep);
if (ISNULLSTARTBLOCK(start_block)) {
/*
@ -2925,15 +2935,13 @@ xfs_iextents_copy(
}
/* Translate to on disk format */
put_unaligned(INT_GET(ep->l0, ARCH_CONVERT),
(__uint64_t*)&dest_ep->l0);
put_unaligned(INT_GET(ep->l1, ARCH_CONVERT),
(__uint64_t*)&dest_ep->l1);
dest_ep++;
put_unaligned(cpu_to_be64(ep->l0), &dp->l0);
put_unaligned(cpu_to_be64(ep->l1), &dp->l1);
dp++;
copied++;
}
ASSERT(copied != 0);
xfs_validate_extents(ifp, copied, 1, XFS_EXTFMT_INODE(ip));
xfs_validate_extents(ifp, copied, XFS_EXTFMT_INODE(ip));
return (copied * (uint)sizeof(xfs_bmbt_rec_t));
}
@ -3024,7 +3032,7 @@ xfs_iflush_fork(
case XFS_DINODE_FMT_DEV:
if (iip->ili_format.ilf_fields & XFS_ILOG_DEV) {
ASSERT(whichfork == XFS_DATA_FORK);
INT_SET(dip->di_u.di_dev, ARCH_CONVERT, ip->i_df.if_u2.if_rdev);
dip->di_u.di_dev = cpu_to_be32(ip->i_df.if_u2.if_rdev);
}
break;
@ -3064,12 +3072,11 @@ xfs_iflush(
xfs_mount_t *mp;
int error;
/* REFERENCED */
xfs_chash_t *ch;
xfs_inode_t *iq;
int clcount; /* count of inodes clustered */
int bufwasdelwri;
struct hlist_node *entry;
enum { INT_DELWRI = (1 << 0), INT_ASYNC = (1 << 1) };
SPLDECL(s);
XFS_STATS_INC(xs_iflush_count);
@ -3183,14 +3190,14 @@ xfs_iflush(
* inode clustering:
* see if other inodes can be gathered into this write
*/
ip->i_chash->chl_buf = bp;
ch = XFS_CHASH(mp, ip->i_blkno);
s = mutex_spinlock(&ch->ch_lock);
spin_lock(&ip->i_cluster->icl_lock);
ip->i_cluster->icl_buf = bp;
clcount = 0;
for (iq = ip->i_cnext; iq != ip; iq = iq->i_cnext) {
hlist_for_each_entry(iq, entry, &ip->i_cluster->icl_inodes, i_cnode) {
if (iq == ip)
continue;
/*
* Do an un-protected check to see if the inode is dirty and
* is a candidate for flushing. These checks will be repeated
@ -3241,7 +3248,7 @@ xfs_iflush(
xfs_iunlock(iq, XFS_ILOCK_SHARED);
}
}
mutex_spinunlock(&ch->ch_lock, s);
spin_unlock(&ip->i_cluster->icl_lock);
if (clcount) {
XFS_STATS_INC(xs_icluster_flushcnt);
@ -3278,7 +3285,7 @@ cluster_corrupt_out:
/* Corruption detected in the clustering loop. Invalidate the
* inode buffer and shut down the filesystem.
*/
mutex_spinunlock(&ch->ch_lock, s);
spin_unlock(&ip->i_cluster->icl_lock);
/*
* Clean up the buffer. If it was B_DELWRI, just release it --
@ -3373,11 +3380,11 @@ xfs_iflush_int(
*/
xfs_synchronize_atime(ip);
if (XFS_TEST_ERROR(INT_GET(dip->di_core.di_magic,ARCH_CONVERT) != XFS_DINODE_MAGIC,
if (XFS_TEST_ERROR(be16_to_cpu(dip->di_core.di_magic) != XFS_DINODE_MAGIC,
mp, XFS_ERRTAG_IFLUSH_1, XFS_RANDOM_IFLUSH_1)) {
xfs_cmn_err(XFS_PTAG_IFLUSH, CE_ALERT, mp,
"xfs_iflush: Bad inode %Lu magic number 0x%x, ptr 0x%p",
ip->i_ino, (int) INT_GET(dip->di_core.di_magic, ARCH_CONVERT), dip);
ip->i_ino, be16_to_cpu(dip->di_core.di_magic), dip);
goto corrupt_out;
}
if (XFS_TEST_ERROR(ip->i_d.di_magic != XFS_DINODE_MAGIC,
@ -3440,7 +3447,7 @@ xfs_iflush_int(
* because if the inode is dirty at all the core must
* be.
*/
xfs_xlate_dinode_core((xfs_caddr_t)&(dip->di_core), &(ip->i_d), -1);
xfs_dinode_to_disk(&dip->di_core, &ip->i_d);
/* Wrap, we never let the log put out DI_MAX_FLUSH */
if (ip->i_d.di_flushiter == DI_MAX_FLUSH)
@ -3460,7 +3467,7 @@ xfs_iflush_int(
* Convert it back.
*/
ASSERT(ip->i_d.di_nlink <= XFS_MAXLINK_1);
INT_SET(dip->di_core.di_onlink, ARCH_CONVERT, ip->i_d.di_nlink);
dip->di_core.di_onlink = cpu_to_be16(ip->i_d.di_nlink);
} else {
/*
* The superblock version has already been bumped,
@ -3468,7 +3475,7 @@ xfs_iflush_int(
* format permanent.
*/
ip->i_d.di_version = XFS_DINODE_VERSION_2;
INT_SET(dip->di_core.di_version, ARCH_CONVERT, XFS_DINODE_VERSION_2);
dip->di_core.di_version = XFS_DINODE_VERSION_2;
ip->i_d.di_onlink = 0;
dip->di_core.di_onlink = 0;
memset(&(ip->i_d.di_pad[0]), 0, sizeof(ip->i_d.di_pad));
@ -3711,7 +3718,7 @@ xfs_ilock_trace(xfs_inode_t *ip, int lock, unsigned int lockflags, inst_t *ra)
/*
* Return a pointer to the extent record at file index idx.
*/
xfs_bmbt_rec_t *
xfs_bmbt_rec_host_t *
xfs_iext_get_ext(
xfs_ifork_t *ifp, /* inode fork pointer */
xfs_extnum_t idx) /* index of target extent */
@ -3744,15 +3751,12 @@ xfs_iext_insert(
xfs_extnum_t count, /* number of inserted items */
xfs_bmbt_irec_t *new) /* items to insert */
{
xfs_bmbt_rec_t *ep; /* extent record pointer */
xfs_extnum_t i; /* extent record index */
ASSERT(ifp->if_flags & XFS_IFEXTENTS);
xfs_iext_add(ifp, idx, count);
for (i = idx; i < idx + count; i++, new++) {
ep = xfs_iext_get_ext(ifp, i);
xfs_bmbt_set_all(ep, new);
}
for (i = idx; i < idx + count; i++, new++)
xfs_bmbt_set_all(xfs_iext_get_ext(ifp, i), new);
}
/*
@ -4203,7 +4207,7 @@ xfs_iext_realloc_direct(
rnew_size = xfs_iroundup(new_size);
}
if (rnew_size != ifp->if_real_bytes) {
ifp->if_u1.if_extents = (xfs_bmbt_rec_t *)
ifp->if_u1.if_extents =
kmem_realloc(ifp->if_u1.if_extents,
rnew_size,
ifp->if_real_bytes,
@ -4266,8 +4270,7 @@ xfs_iext_inline_to_direct(
xfs_ifork_t *ifp, /* inode fork pointer */
int new_size) /* number of extents in file */
{
ifp->if_u1.if_extents = (xfs_bmbt_rec_t *)
kmem_alloc(new_size, KM_SLEEP);
ifp->if_u1.if_extents = kmem_alloc(new_size, KM_SLEEP);
memset(ifp->if_u1.if_extents, 0, new_size);
if (ifp->if_bytes) {
memcpy(ifp->if_u1.if_extents, ifp->if_u2.if_inline_ext,
@ -4310,7 +4313,7 @@ void
xfs_iext_indirect_to_direct(
xfs_ifork_t *ifp) /* inode fork pointer */
{
xfs_bmbt_rec_t *ep; /* extent record pointer */
xfs_bmbt_rec_host_t *ep; /* extent record pointer */
xfs_extnum_t nextents; /* number of extents in file */
int size; /* size of file extents */
@ -4362,15 +4365,15 @@ xfs_iext_destroy(
/*
* Return a pointer to the extent record for file system block bno.
*/
xfs_bmbt_rec_t * /* pointer to found extent record */
xfs_bmbt_rec_host_t * /* pointer to found extent record */
xfs_iext_bno_to_ext(
xfs_ifork_t *ifp, /* inode fork pointer */
xfs_fileoff_t bno, /* block number to search for */
xfs_extnum_t *idxp) /* index of target extent */
{
xfs_bmbt_rec_t *base; /* pointer to first extent */
xfs_bmbt_rec_host_t *base; /* pointer to first extent */
xfs_filblks_t blockcount = 0; /* number of blocks in extent */
xfs_bmbt_rec_t *ep = NULL; /* pointer to target extent */
xfs_bmbt_rec_host_t *ep = NULL; /* pointer to target extent */
xfs_ext_irec_t *erp = NULL; /* indirection array pointer */
int high; /* upper boundary in search */
xfs_extnum_t idx = 0; /* index of target extent */
@ -4545,8 +4548,7 @@ xfs_iext_irec_init(
kmem_alloc(sizeof(xfs_ext_irec_t), KM_SLEEP);
if (nextents == 0) {
ifp->if_u1.if_extents = (xfs_bmbt_rec_t *)
kmem_alloc(XFS_IEXT_BUFSZ, KM_SLEEP);
ifp->if_u1.if_extents = kmem_alloc(XFS_IEXT_BUFSZ, KM_SLEEP);
} else if (!ifp->if_real_bytes) {
xfs_iext_inline_to_direct(ifp, XFS_IEXT_BUFSZ);
} else if (ifp->if_real_bytes < XFS_IEXT_BUFSZ) {
@ -4594,8 +4596,7 @@ xfs_iext_irec_new(
/* Initialize new extent record */
erp = ifp->if_u1.if_ext_irec;
erp[erp_idx].er_extbuf = (xfs_bmbt_rec_t *)
kmem_alloc(XFS_IEXT_BUFSZ, KM_SLEEP);
erp[erp_idx].er_extbuf = kmem_alloc(XFS_IEXT_BUFSZ, KM_SLEEP);
ifp->if_real_bytes = nlists * XFS_IEXT_BUFSZ;
memset(erp[erp_idx].er_extbuf, 0, XFS_IEXT_BUFSZ);
erp[erp_idx].er_extcount = 0;
@ -4727,7 +4728,7 @@ void
xfs_iext_irec_compact_full(
xfs_ifork_t *ifp) /* inode fork pointer */
{
xfs_bmbt_rec_t *ep, *ep_next; /* extent record pointers */
xfs_bmbt_rec_host_t *ep, *ep_next; /* extent record pointers */
xfs_ext_irec_t *erp, *erp_next; /* extent irec pointers */
int erp_idx = 0; /* extent irec index */
int ext_avail; /* empty entries in ex list */

View file

@ -18,6 +18,10 @@
#ifndef __XFS_INODE_H__
#define __XFS_INODE_H__
struct xfs_dinode;
struct xfs_dinode_core;
/*
* Fork identifiers.
*/
@ -44,7 +48,7 @@
* it is possible that a third level of indirection may be required.
*/
typedef struct xfs_ext_irec {
xfs_bmbt_rec_t *er_extbuf; /* block of extent records */
xfs_bmbt_rec_host_t *er_extbuf; /* block of extent records */
xfs_extnum_t er_extoff; /* extent offset in file */
xfs_extnum_t er_extcount; /* number of extents in page/block */
} xfs_ext_irec_t;
@ -65,12 +69,12 @@ typedef struct xfs_ifork {
unsigned char if_ext_max; /* max # of extent records */
xfs_extnum_t if_lastex; /* last if_extents used */
union {
xfs_bmbt_rec_t *if_extents; /* linear map file exts */
xfs_bmbt_rec_host_t *if_extents;/* linear map file exts */
xfs_ext_irec_t *if_ext_irec; /* irec map file exts */
char *if_data; /* inline file data */
} if_u1;
union {
xfs_bmbt_rec_t if_inline_ext[XFS_INLINE_EXTS];
xfs_bmbt_rec_host_t if_inline_ext[XFS_INLINE_EXTS];
/* very small file extents */
char if_inline_data[XFS_INLINE_DATA];
/* very small file data */
@ -102,7 +106,6 @@ typedef struct xfs_ifork {
#ifdef __KERNEL__
struct bhv_desc;
struct bhv_vnode;
struct cred;
struct ktrace;
struct xfs_buf;
@ -168,41 +171,18 @@ typedef struct xfs_iocore {
extern void xfs_iocore_inode_init(struct xfs_inode *);
extern void xfs_iocore_inode_reinit(struct xfs_inode *);
/*
* This is the type used in the xfs inode hash table.
* An array of these is allocated for each mounted
* file system to hash the inodes for that file system.
* This is the xfs inode cluster structure. This structure is used by
* xfs_iflush to find inodes that share a cluster and can be flushed to disk at
* the same time.
*/
typedef struct xfs_ihash {
struct xfs_inode *ih_next;
rwlock_t ih_lock;
uint ih_version;
} xfs_ihash_t;
#define XFS_IHASH(mp,ino) ((mp)->m_ihash + (((uint)(ino)) % (mp)->m_ihsize))
/*
* This is the xfs inode cluster hash. This hash is used by xfs_iflush to
* find inodes that share a cluster and can be flushed to disk at the same
* time.
*/
typedef struct xfs_chashlist {
struct xfs_chashlist *chl_next;
struct xfs_chashlist *chl_prev;
struct xfs_inode *chl_ip;
xfs_daddr_t chl_blkno; /* starting block number of
typedef struct xfs_icluster {
struct hlist_head icl_inodes; /* list of inodes on cluster */
xfs_daddr_t icl_blkno; /* starting block number of
* the cluster */
struct xfs_buf *chl_buf; /* the inode buffer */
} xfs_chashlist_t;
typedef struct xfs_chash {
xfs_chashlist_t *ch_list;
lock_t ch_lock;
} xfs_chash_t;
#define XFS_CHASH(mp,blk) ((mp)->m_chash + (((uint)blk) % (mp)->m_chsize))
struct xfs_buf *icl_buf; /* the inode buffer */
lock_t icl_lock; /* inode list lock */
} xfs_icluster_t;
/*
* This is the xfs in-core inode structure.
@ -227,25 +207,56 @@ typedef struct xfs_chash {
* chain off the mount structure by xfs_sync calls.
*/
typedef struct xfs_ictimestamp {
__int32_t t_sec; /* timestamp seconds */
__int32_t t_nsec; /* timestamp nanoseconds */
} xfs_ictimestamp_t;
/*
* NOTE: This structure must be kept identical to struct xfs_dinode_core
* in xfs_dinode.h except for the endianess annotations.
*/
typedef struct xfs_icdinode {
__uint16_t di_magic; /* inode magic # = XFS_DINODE_MAGIC */
__uint16_t di_mode; /* mode and type of file */
__int8_t di_version; /* inode version */
__int8_t di_format; /* format of di_c data */
__uint16_t di_onlink; /* old number of links to file */
__uint32_t di_uid; /* owner's user id */
__uint32_t di_gid; /* owner's group id */
__uint32_t di_nlink; /* number of links to file */
__uint16_t di_projid; /* owner's project id */
__uint8_t di_pad[8]; /* unused, zeroed space */
__uint16_t di_flushiter; /* incremented on flush */
xfs_ictimestamp_t di_atime; /* time last accessed */
xfs_ictimestamp_t di_mtime; /* time last modified */
xfs_ictimestamp_t di_ctime; /* time created/inode modified */
xfs_fsize_t di_size; /* number of bytes in file */
xfs_drfsbno_t di_nblocks; /* # of direct & btree blocks used */
xfs_extlen_t di_extsize; /* basic/minimum extent size for file */
xfs_extnum_t di_nextents; /* number of extents in data fork */
xfs_aextnum_t di_anextents; /* number of extents in attribute fork*/
__uint8_t di_forkoff; /* attr fork offs, <<3 for 64b align */
__int8_t di_aformat; /* format of attr fork's data */
__uint32_t di_dmevmask; /* DMIG event mask */
__uint16_t di_dmstate; /* DMIG state info */
__uint16_t di_flags; /* random flags, XFS_DIFLAG_... */
__uint32_t di_gen; /* generation number */
} xfs_icdinode_t;
typedef struct {
struct xfs_ihash *ip_hash; /* pointer to hash header */
struct xfs_inode *ip_next; /* inode hash link forw */
struct xfs_inode *ip_mnext; /* next inode in mount list */
struct xfs_inode *ip_mprev; /* ptr to prev inode */
struct xfs_inode **ip_prevp; /* ptr to prev i_next */
struct xfs_mount *ip_mount; /* fs mount struct ptr */
} xfs_iptr_t;
typedef struct xfs_inode {
/* Inode linking and identification information. */
struct xfs_ihash *i_hash; /* pointer to hash header */
struct xfs_inode *i_next; /* inode hash link forw */
struct xfs_inode *i_mnext; /* next inode in mount list */
struct xfs_inode *i_mprev; /* ptr to prev inode */
struct xfs_inode **i_prevp; /* ptr to prev i_next */
struct xfs_mount *i_mount; /* fs mount struct ptr */
struct list_head i_reclaim; /* reclaim list */
struct bhv_desc i_bhv_desc; /* inode behavior descriptor*/
bhv_vnode_t *i_vnode; /* vnode backpointer */
struct xfs_dquot *i_udquot; /* user dquot */
struct xfs_dquot *i_gdquot; /* group dquot */
@ -282,13 +293,16 @@ typedef struct xfs_inode {
unsigned int i_gen; /* generation count */
unsigned int i_delayed_blks; /* count of delay alloc blks */
xfs_dinode_core_t i_d; /* most of ondisk inode */
xfs_chashlist_t *i_chash; /* cluster hash list header */
struct xfs_inode *i_cnext; /* cluster hash link forward */
struct xfs_inode *i_cprev; /* cluster hash link backward */
xfs_icdinode_t i_d; /* most of ondisk inode */
xfs_icluster_t *i_cluster; /* cluster list header */
struct hlist_node i_cnode; /* cluster link node */
xfs_fsize_t i_size; /* in-memory size */
atomic_t i_iocount; /* outstanding I/O count */
/* Trace buffers per inode. */
#ifdef XFS_VNODE_TRACE
struct ktrace *i_trace; /* general inode trace */
#endif
#ifdef XFS_BMAP_TRACE
struct ktrace *i_xtrace; /* inode extent list trace */
#endif
@ -349,6 +363,19 @@ xfs_iflags_test(xfs_inode_t *ip, unsigned short flags)
spin_unlock(&ip->i_flags_lock);
return ret;
}
static inline int
xfs_iflags_test_and_clear(xfs_inode_t *ip, unsigned short flags)
{
int ret;
spin_lock(&ip->i_flags_lock);
ret = ip->i_flags & flags;
if (ret)
ip->i_flags &= ~flags;
spin_unlock(&ip->i_flags_lock);
return ret;
}
#endif /* __KERNEL__ */
@ -380,6 +407,9 @@ xfs_iflags_test(xfs_inode_t *ip, unsigned short flags)
#define XFS_IRECLAIMABLE 0x0020 /* inode can be reclaimed */
#define XFS_INEW 0x0040
#define XFS_IFILESTREAM 0x0080 /* inode is in a filestream directory */
#define XFS_IMODIFIED 0x0100 /* XFS inode state possibly differs */
/* to the Linux inode state. */
#define XFS_ITRUNCATED 0x0200 /* truncated down so flush-on-close */
/*
* Flags for inode locking.
@ -454,20 +484,17 @@ xfs_iflags_test(xfs_inode_t *ip, unsigned short flags)
#define XFS_ITRUNC_DEFINITE 0x1
#define XFS_ITRUNC_MAYBE 0x2
#define XFS_ITOV(ip) BHV_TO_VNODE(XFS_ITOBHV(ip))
#define XFS_ITOV_NULL(ip) BHV_TO_VNODE_NULL(XFS_ITOBHV(ip))
#define XFS_ITOBHV(ip) ((struct bhv_desc *)(&((ip)->i_bhv_desc)))
#define XFS_BHVTOI(bhvp) ((xfs_inode_t *)((char *)(bhvp) - \
(char *)&(((xfs_inode_t *)0)->i_bhv_desc)))
#define BHV_IS_XFS(bdp) (BHV_OPS(bdp) == &xfs_vnodeops)
#define XFS_ITOV(ip) ((ip)->i_vnode)
#define XFS_ITOV_NULL(ip) ((ip)->i_vnode)
/*
* For multiple groups support: if S_ISGID bit is set in the parent
* directory, group of new file is set to that of the parent, and
* new subdirectory gets S_ISGID bit from parent.
*/
#define XFS_INHERIT_GID(pip, vfsp) \
(((vfsp)->vfs_flag & VFS_GRPID) || ((pip)->i_d.di_mode & S_ISGID))
#define XFS_INHERIT_GID(pip) \
(((pip)->i_mount->m_flags & XFS_MOUNT_GRPID) || \
((pip)->i_d.di_mode & S_ISGID))
/*
* Flags for xfs_iget()
@ -480,11 +507,9 @@ xfs_iflags_test(xfs_inode_t *ip, unsigned short flags)
*/
void xfs_ihash_init(struct xfs_mount *);
void xfs_ihash_free(struct xfs_mount *);
void xfs_chash_init(struct xfs_mount *);
void xfs_chash_free(struct xfs_mount *);
xfs_inode_t *xfs_inode_incore(struct xfs_mount *, xfs_ino_t,
struct xfs_trans *);
void xfs_inode_lock_init(xfs_inode_t *, struct bhv_vnode *);
void xfs_inode_lock_init(xfs_inode_t *, bhv_vnode_t *);
int xfs_iget(struct xfs_mount *, struct xfs_trans *, xfs_ino_t,
uint, uint, xfs_inode_t **, xfs_daddr_t);
void xfs_iput(xfs_inode_t *, uint);
@ -506,7 +531,7 @@ int xfs_finish_reclaim_all(struct xfs_mount *, int);
* xfs_inode.c prototypes.
*/
int xfs_itobp(struct xfs_mount *, struct xfs_trans *,
xfs_inode_t *, xfs_dinode_t **, struct xfs_buf **,
xfs_inode_t *, struct xfs_dinode **, struct xfs_buf **,
xfs_daddr_t, uint);
int xfs_iread(struct xfs_mount *, struct xfs_trans *, xfs_ino_t,
xfs_inode_t **, xfs_daddr_t, uint);
@ -514,8 +539,11 @@ int xfs_iread_extents(struct xfs_trans *, xfs_inode_t *, int);
int xfs_ialloc(struct xfs_trans *, xfs_inode_t *, mode_t,
xfs_nlink_t, xfs_dev_t, struct cred *, xfs_prid_t,
int, struct xfs_buf **, boolean_t *, xfs_inode_t **);
void xfs_xlate_dinode_core(xfs_caddr_t, struct xfs_dinode_core *,
int);
void xfs_dinode_from_disk(struct xfs_icdinode *,
struct xfs_dinode_core *);
void xfs_dinode_to_disk(struct xfs_dinode_core *,
struct xfs_icdinode *);
uint xfs_ip2xflags(struct xfs_inode *);
uint xfs_dic2xflags(struct xfs_dinode_core *);
int xfs_ifree(struct xfs_trans *, xfs_inode_t *,
@ -545,11 +573,9 @@ void xfs_ichgtime(xfs_inode_t *, int);
xfs_fsize_t xfs_file_last_byte(xfs_inode_t *);
void xfs_lock_inodes(xfs_inode_t **, int, int, uint);
xfs_inode_t *xfs_vtoi(struct bhv_vnode *vp);
void xfs_synchronize_atime(xfs_inode_t *);
xfs_bmbt_rec_t *xfs_iext_get_ext(xfs_ifork_t *, xfs_extnum_t);
xfs_bmbt_rec_host_t *xfs_iext_get_ext(xfs_ifork_t *, xfs_extnum_t);
void xfs_iext_insert(xfs_ifork_t *, xfs_extnum_t, xfs_extnum_t,
xfs_bmbt_irec_t *);
void xfs_iext_add(xfs_ifork_t *, xfs_extnum_t, int);
@ -564,7 +590,7 @@ void xfs_iext_indirect_to_direct(xfs_ifork_t *);
void xfs_iext_direct_to_inline(xfs_ifork_t *, xfs_extnum_t);
void xfs_iext_inline_to_direct(xfs_ifork_t *, int);
void xfs_iext_destroy(xfs_ifork_t *);
xfs_bmbt_rec_t *xfs_iext_bno_to_ext(xfs_ifork_t *, xfs_fileoff_t, int *);
xfs_bmbt_rec_host_t *xfs_iext_bno_to_ext(xfs_ifork_t *, xfs_fileoff_t, int *);
xfs_ext_irec_t *xfs_iext_bno_to_irec(xfs_ifork_t *, xfs_fileoff_t, int *);
xfs_ext_irec_t *xfs_iext_idx_to_irec(xfs_ifork_t *, xfs_extnum_t *, int *, int);
void xfs_iext_irec_init(xfs_ifork_t *);
@ -589,7 +615,7 @@ void xfs_inobp_check(struct xfs_mount *, struct xfs_buf *);
#define xfs_inobp_check(mp, bp)
#endif /* DEBUG */
extern struct kmem_zone *xfs_chashlist_zone;
extern struct kmem_zone *xfs_icluster_zone;
extern struct kmem_zone *xfs_ifork_zone;
extern struct kmem_zone *xfs_inode_zone;
extern struct kmem_zone *xfs_ili_zone;

View file

@ -57,11 +57,11 @@ xfs_size_fn(
STATIC int
xfs_ioinit(
struct bhv_vfs *vfsp,
struct xfs_mount *mp,
struct xfs_mount_args *mntargs,
int flags)
{
return xfs_mountfs(vfsp, XFS_VFSTOM(vfsp), flags);
return xfs_mountfs(mp, flags);
}
xfs_ioops_t xfs_iocore_xfs = {

View file

@ -135,14 +135,10 @@ xfs_imap_to_bmap(
int flags)
{
xfs_mount_t *mp;
xfs_fsize_t nisize;
int pbm;
xfs_fsblock_t start_block;
mp = io->io_mount;
nisize = XFS_SIZE(mp, io);
if (io->io_new_size > nisize)
nisize = io->io_new_size;
for (pbm = 0; imaps && pbm < iomaps; imaps--, iomapp++, imap++, pbm++) {
iomapp->iomap_offset = XFS_FSB_TO_B(mp, imap->br_startoff);
@ -169,10 +165,6 @@ xfs_imap_to_bmap(
iomapp->iomap_flags |= IOMAP_UNWRITTEN;
}
if ((iomapp->iomap_offset + iomapp->iomap_bsize) >= nisize) {
iomapp->iomap_flags |= IOMAP_EOF;
}
offset += iomapp->iomap_bsize - iomapp->iomap_delta;
}
return pbm; /* Return the number filled */

View file

@ -23,7 +23,6 @@
typedef enum { /* iomap_flags values */
IOMAP_READ = 0, /* mapping for a read */
IOMAP_EOF = 0x01, /* mapping contains EOF */
IOMAP_HOLE = 0x02, /* mapping covers a hole */
IOMAP_DELAY = 0x04, /* mapping covers delalloc region */
IOMAP_REALTIME = 0x10, /* mapping on the realtime device */

View file

@ -57,7 +57,7 @@ xfs_bulkstat_one_iget(
xfs_bstat_t *buf, /* return buffer */
int *stat) /* BULKSTAT_RV_... */
{
xfs_dinode_core_t *dic; /* dinode core info pointer */
xfs_icdinode_t *dic; /* dinode core info pointer */
xfs_inode_t *ip; /* incore inode pointer */
bhv_vnode_t *vp;
int error;
@ -151,37 +151,37 @@ xfs_bulkstat_one_dinode(
* the new format. We don't change the version number so that we
* can distinguish this from a real new format inode.
*/
if (INT_GET(dic->di_version, ARCH_CONVERT) == XFS_DINODE_VERSION_1) {
buf->bs_nlink = INT_GET(dic->di_onlink, ARCH_CONVERT);
if (dic->di_version == XFS_DINODE_VERSION_1) {
buf->bs_nlink = be16_to_cpu(dic->di_onlink);
buf->bs_projid = 0;
} else {
buf->bs_nlink = INT_GET(dic->di_nlink, ARCH_CONVERT);
buf->bs_projid = INT_GET(dic->di_projid, ARCH_CONVERT);
buf->bs_nlink = be32_to_cpu(dic->di_nlink);
buf->bs_projid = be16_to_cpu(dic->di_projid);
}
buf->bs_ino = ino;
buf->bs_mode = INT_GET(dic->di_mode, ARCH_CONVERT);
buf->bs_uid = INT_GET(dic->di_uid, ARCH_CONVERT);
buf->bs_gid = INT_GET(dic->di_gid, ARCH_CONVERT);
buf->bs_size = INT_GET(dic->di_size, ARCH_CONVERT);
buf->bs_atime.tv_sec = INT_GET(dic->di_atime.t_sec, ARCH_CONVERT);
buf->bs_atime.tv_nsec = INT_GET(dic->di_atime.t_nsec, ARCH_CONVERT);
buf->bs_mtime.tv_sec = INT_GET(dic->di_mtime.t_sec, ARCH_CONVERT);
buf->bs_mtime.tv_nsec = INT_GET(dic->di_mtime.t_nsec, ARCH_CONVERT);
buf->bs_ctime.tv_sec = INT_GET(dic->di_ctime.t_sec, ARCH_CONVERT);
buf->bs_ctime.tv_nsec = INT_GET(dic->di_ctime.t_nsec, ARCH_CONVERT);
buf->bs_mode = be16_to_cpu(dic->di_mode);
buf->bs_uid = be32_to_cpu(dic->di_uid);
buf->bs_gid = be32_to_cpu(dic->di_gid);
buf->bs_size = be64_to_cpu(dic->di_size);
buf->bs_atime.tv_sec = be32_to_cpu(dic->di_atime.t_sec);
buf->bs_atime.tv_nsec = be32_to_cpu(dic->di_atime.t_nsec);
buf->bs_mtime.tv_sec = be32_to_cpu(dic->di_mtime.t_sec);
buf->bs_mtime.tv_nsec = be32_to_cpu(dic->di_mtime.t_nsec);
buf->bs_ctime.tv_sec = be32_to_cpu(dic->di_ctime.t_sec);
buf->bs_ctime.tv_nsec = be32_to_cpu(dic->di_ctime.t_nsec);
buf->bs_xflags = xfs_dic2xflags(dic);
buf->bs_extsize = INT_GET(dic->di_extsize, ARCH_CONVERT) << mp->m_sb.sb_blocklog;
buf->bs_extents = INT_GET(dic->di_nextents, ARCH_CONVERT);
buf->bs_gen = INT_GET(dic->di_gen, ARCH_CONVERT);
buf->bs_extsize = be32_to_cpu(dic->di_extsize) << mp->m_sb.sb_blocklog;
buf->bs_extents = be32_to_cpu(dic->di_nextents);
buf->bs_gen = be32_to_cpu(dic->di_gen);
memset(buf->bs_pad, 0, sizeof(buf->bs_pad));
buf->bs_dmevmask = INT_GET(dic->di_dmevmask, ARCH_CONVERT);
buf->bs_dmstate = INT_GET(dic->di_dmstate, ARCH_CONVERT);
buf->bs_aextents = INT_GET(dic->di_anextents, ARCH_CONVERT);
buf->bs_dmevmask = be32_to_cpu(dic->di_dmevmask);
buf->bs_dmstate = be16_to_cpu(dic->di_dmstate);
buf->bs_aextents = be16_to_cpu(dic->di_anextents);
switch (INT_GET(dic->di_format, ARCH_CONVERT)) {
switch (dic->di_format) {
case XFS_DINODE_FMT_DEV:
buf->bs_rdev = INT_GET(dip->di_u.di_dev, ARCH_CONVERT);
buf->bs_rdev = be32_to_cpu(dip->di_u.di_dev);
buf->bs_blksize = BLKDEV_IOSIZE;
buf->bs_blocks = 0;
break;
@ -195,7 +195,7 @@ xfs_bulkstat_one_dinode(
case XFS_DINODE_FMT_BTREE:
buf->bs_rdev = 0;
buf->bs_blksize = mp->m_sb.sb_blocksize;
buf->bs_blocks = INT_GET(dic->di_nblocks, ARCH_CONVERT);
buf->bs_blocks = be64_to_cpu(dic->di_nblocks);
break;
}
@ -290,16 +290,23 @@ xfs_bulkstat_use_dinode(
return 1;
dip = (xfs_dinode_t *)
xfs_buf_offset(bp, clustidx << mp->m_sb.sb_inodelog);
if (INT_GET(dip->di_core.di_magic, ARCH_CONVERT) != XFS_DINODE_MAGIC ||
!XFS_DINODE_GOOD_VERSION(
INT_GET(dip->di_core.di_version, ARCH_CONVERT)))
/*
* Check the buffer containing the on-disk inode for di_nlink == 0.
* This is to prevent xfs_bulkstat from picking up just reclaimed
* inodes that have their in-core state initialized but not flushed
* to disk yet. This is a temporary hack that would require a proper
* fix in the future.
*/
if (be16_to_cpu(dip->di_core.di_magic) != XFS_DINODE_MAGIC ||
!XFS_DINODE_GOOD_VERSION(dip->di_core.di_version) ||
!dip->di_core.di_nlink)
return 0;
if (flags & BULKSTAT_FG_QUICK) {
*dipp = dip;
return 1;
}
/* BULKSTAT_FG_INLINE: if attr fork is local, or not there, use it */
aformat = INT_GET(dip->di_core.di_aformat, ARCH_CONVERT);
aformat = dip->di_core.di_aformat;
if ((XFS_CFORK_Q(&dip->di_core) == 0) ||
(aformat == XFS_DINODE_FMT_LOCAL) ||
(aformat == XFS_DINODE_FMT_EXTENTS && !dip->di_core.di_anextents)) {
@ -612,21 +619,25 @@ xfs_bulkstat(
}
}
}
ino = XFS_AGINO_TO_INO(mp, agno, agino);
bno = XFS_AGB_TO_DADDR(mp, agno, agbno);
/*
* Skip if this inode is free.
*/
if (XFS_INOBT_MASK(chunkidx) & irbp->ir_free)
if (XFS_INOBT_MASK(chunkidx) & irbp->ir_free) {
lastino = ino;
continue;
}
/*
* Count used inodes as free so we can tell
* when the chunk is used up.
*/
irbp->ir_freecount++;
ino = XFS_AGINO_TO_INO(mp, agno, agino);
bno = XFS_AGB_TO_DADDR(mp, agno, agbno);
if (!xfs_bulkstat_use_dinode(mp, flags, bp,
clustidx, &dip))
clustidx, &dip)) {
lastino = ino;
continue;
}
/*
* If we need to do an iget, cannot hold bp.
* Drop it, until starting the next cluster.
@ -687,8 +698,7 @@ xfs_bulkstat(
if (end_of_ag) {
agno++;
agino = 0;
} else
agino = XFS_INO_TO_AGINO(mp, lastino);
}
} else
break;
}

View file

@ -252,6 +252,29 @@ xlog_grant_add_space(struct log *log, int bytes)
xlog_grant_add_space_reserve(log, bytes);
}
static void
xlog_tic_reset_res(xlog_ticket_t *tic)
{
tic->t_res_num = 0;
tic->t_res_arr_sum = 0;
tic->t_res_num_ophdrs = 0;
}
static void
xlog_tic_add_region(xlog_ticket_t *tic, uint len, uint type)
{
if (tic->t_res_num == XLOG_TIC_LEN_MAX) {
/* add to overflow and start again */
tic->t_res_o_flow += tic->t_res_arr_sum;
tic->t_res_num = 0;
tic->t_res_arr_sum = 0;
}
tic->t_res_arr[tic->t_res_num].r_len = len;
tic->t_res_arr[tic->t_res_num].r_type = type;
tic->t_res_arr_sum += len;
tic->t_res_num++;
}
/*
* NOTES:
@ -486,7 +509,7 @@ xfs_log_mount(xfs_mount_t *mp,
cmn_err(CE_NOTE,
"!Mounting filesystem \"%s\" in no-recovery mode. Filesystem will be inconsistent.",
mp->m_fsname);
ASSERT(XFS_MTOVFS(mp)->vfs_flag & VFS_RDONLY);
ASSERT(mp->m_flags & XFS_MOUNT_RDONLY);
}
mp->m_log = xlog_alloc_log(mp, log_target, blk_offset, num_bblks);
@ -496,16 +519,15 @@ xfs_log_mount(xfs_mount_t *mp,
* just worked.
*/
if (!(mp->m_flags & XFS_MOUNT_NORECOVERY)) {
bhv_vfs_t *vfsp = XFS_MTOVFS(mp);
int error, readonly = (vfsp->vfs_flag & VFS_RDONLY);
int error, readonly = (mp->m_flags & XFS_MOUNT_RDONLY);
if (readonly)
vfsp->vfs_flag &= ~VFS_RDONLY;
mp->m_flags &= ~XFS_MOUNT_RDONLY;
error = xlog_recover(mp->m_log);
if (readonly)
vfsp->vfs_flag |= VFS_RDONLY;
mp->m_flags |= XFS_MOUNT_RDONLY;
if (error) {
cmn_err(CE_WARN, "XFS: log mount/recovery failed: error %d", error);
xlog_dealloc_log(mp->m_log);
@ -537,7 +559,7 @@ xfs_log_mount_finish(xfs_mount_t *mp, int mfsi_flags)
error = xlog_recover_finish(mp->m_log, mfsi_flags);
else {
error = 0;
ASSERT(XFS_MTOVFS(mp)->vfs_flag & VFS_RDONLY);
ASSERT(mp->m_flags & XFS_MOUNT_RDONLY);
}
return error;
@ -597,7 +619,7 @@ xfs_log_unmount_write(xfs_mount_t *mp)
* Don't write out unmount record on read-only mounts.
* Or, if we are doing a forced umount (typically because of IO errors).
*/
if (XFS_MTOVFS(mp)->vfs_flag & VFS_RDONLY)
if (mp->m_flags & XFS_MOUNT_RDONLY)
return 0;
xfs_log_force(mp, 0, XFS_LOG_FORCE|XFS_LOG_SYNC);
@ -948,6 +970,19 @@ xlog_iodone(xfs_buf_t *bp)
*/
l = iclog->ic_log;
/*
* If the ordered flag has been removed by a lower
* layer, it means the underlyin device no longer supports
* barrier I/O. Warn loudly and turn off barriers.
*/
if ((l->l_mp->m_flags & XFS_MOUNT_BARRIER) && !XFS_BUF_ORDERED(bp)) {
l->l_mp->m_flags &= ~XFS_MOUNT_BARRIER;
xfs_fs_cmn_err(CE_WARN, l->l_mp,
"xlog_iodone: Barriers are no longer supported"
" by device. Disabling barriers\n");
xfs_buftrace("XLOG_IODONE BARRIERS OFF", bp);
}
/*
* Race to shutdown the filesystem if we see an error.
*/
@ -1012,10 +1047,7 @@ xlog_bdstrat_cb(struct xfs_buf *bp)
/*
* Return size of each in-core log record buffer.
*
* Low memory machines only get 2 16KB buffers. We don't want to waste
* memory here. However, all other machines get at least 2 32KB buffers.
* The number is hard coded because we don't care about the minimum
* memory size, just 32MB systems.
* All machines get 8 x 32KB buffers by default, unless tuned otherwise.
*
* If the filesystem blocksize is too large, we may need to choose a
* larger size since the directory code currently logs entire blocks.
@ -1028,17 +1060,10 @@ xlog_get_iclog_buffer_size(xfs_mount_t *mp,
int size;
int xhdrs;
if (mp->m_logbufs <= 0) {
if (xfs_physmem <= btoc(128*1024*1024)) {
log->l_iclog_bufs = XLOG_MIN_ICLOGS;
} else if (xfs_physmem <= btoc(400*1024*1024)) {
log->l_iclog_bufs = XLOG_MED_ICLOGS;
} else { /* 256K with 32K bufs */
log->l_iclog_bufs = XLOG_MAX_ICLOGS;
}
} else {
if (mp->m_logbufs <= 0)
log->l_iclog_bufs = XLOG_MAX_ICLOGS;
else
log->l_iclog_bufs = mp->m_logbufs;
}
/*
* Buffer size passed in from mount system call.
@ -1069,18 +1094,9 @@ xlog_get_iclog_buffer_size(xfs_mount_t *mp,
goto done;
}
/*
* Special case machines that have less than 32MB of memory.
* All machines with more memory use 32KB buffers.
*/
if (xfs_physmem <= btoc(32*1024*1024)) {
/* Don't change; min configuration */
log->l_iclog_size = XLOG_RECORD_BSIZE; /* 16k */
log->l_iclog_size_log = XLOG_RECORD_BSHIFT;
} else {
log->l_iclog_size = XLOG_BIG_RECORD_BSIZE; /* 32k */
log->l_iclog_size_log = XLOG_BIG_RECORD_BSHIFT;
}
/* All machines use 32KB buffers by default. */
log->l_iclog_size = XLOG_BIG_RECORD_BSIZE;
log->l_iclog_size_log = XLOG_BIG_RECORD_BSHIFT;
/* the default log size is 16k or 32k which is one header sector */
log->l_iclog_hsize = BBSIZE;
@ -1771,14 +1787,14 @@ xlog_write(xfs_mount_t * mp,
len = 0;
if (ticket->t_flags & XLOG_TIC_INITED) { /* acct for start rec of xact */
len += sizeof(xlog_op_header_t);
XLOG_TIC_ADD_OPHDR(ticket);
ticket->t_res_num_ophdrs++;
}
for (index = 0; index < nentries; index++) {
len += sizeof(xlog_op_header_t); /* each region gets >= 1 */
XLOG_TIC_ADD_OPHDR(ticket);
ticket->t_res_num_ophdrs++;
len += reg[index].i_len;
XLOG_TIC_ADD_REGION(ticket, reg[index].i_len, reg[index].i_type);
xlog_tic_add_region(ticket, reg[index].i_len, reg[index].i_type);
}
contwr = *start_lsn = 0;
@ -1887,7 +1903,7 @@ xlog_write(xfs_mount_t * mp,
len += sizeof(xlog_op_header_t); /* from splitting of region */
/* account for new log op header */
ticket->t_curr_res -= sizeof(xlog_op_header_t);
XLOG_TIC_ADD_OPHDR(ticket);
ticket->t_res_num_ophdrs++;
}
xlog_verify_dest_ptr(log, ptr);
@ -2385,7 +2401,7 @@ restart:
*/
if (log_offset == 0) {
ticket->t_curr_res -= log->l_iclog_hsize;
XLOG_TIC_ADD_REGION(ticket,
xlog_tic_add_region(ticket,
log->l_iclog_hsize,
XLOG_REG_TYPE_LRHEADER);
INT_SET(head->h_cycle, ARCH_CONVERT, log->l_curr_cycle);
@ -2573,7 +2589,7 @@ xlog_regrant_write_log_space(xlog_t *log,
#endif
tic->t_curr_res = tic->t_unit_res;
XLOG_TIC_RESET_RES(tic);
xlog_tic_reset_res(tic);
if (tic->t_cnt > 0)
return 0;
@ -2714,7 +2730,7 @@ xlog_regrant_reserve_log_space(xlog_t *log,
s = GRANT_LOCK(log);
xlog_grant_sub_space(log, ticket->t_curr_res);
ticket->t_curr_res = ticket->t_unit_res;
XLOG_TIC_RESET_RES(ticket);
xlog_tic_reset_res(ticket);
xlog_trace_loggrant(log, ticket,
"xlog_regrant_reserve_log_space: sub current res");
xlog_verify_grant_head(log, 1);
@ -2731,7 +2747,7 @@ xlog_regrant_reserve_log_space(xlog_t *log,
xlog_verify_grant_head(log, 0);
GRANT_UNLOCK(log, s);
ticket->t_curr_res = ticket->t_unit_res;
XLOG_TIC_RESET_RES(ticket);
xlog_tic_reset_res(ticket);
} /* xlog_regrant_reserve_log_space */
@ -3354,7 +3370,7 @@ xlog_ticket_get(xlog_t *log,
tic->t_flags |= XLOG_TIC_PERM_RESERV;
sv_init(&(tic->t_sema), SV_DEFAULT, "logtick");
XLOG_TIC_RESET_RES(tic);
xlog_tic_reset_res(tic);
return tic;
} /* xlog_ticket_get */

View file

@ -30,17 +30,16 @@ struct xfs_mount;
*/
#define XLOG_MIN_ICLOGS 2
#define XLOG_MED_ICLOGS 4
#define XLOG_MAX_ICLOGS 8
#define XLOG_HEADER_MAGIC_NUM 0xFEEDbabe /* Invalid cycle number */
#define XLOG_VERSION_1 1
#define XLOG_VERSION_2 2 /* Large IClogs, Log sunit */
#define XLOG_VERSION_OKBITS (XLOG_VERSION_1 | XLOG_VERSION_2)
#define XLOG_RECORD_BSIZE (16*1024) /* eventually 32k */
#define XLOG_MIN_RECORD_BSIZE (16*1024) /* eventually 32k */
#define XLOG_BIG_RECORD_BSIZE (32*1024) /* 32k buffers */
#define XLOG_MAX_RECORD_BSIZE (256*1024)
#define XLOG_HEADER_CYCLE_SIZE (32*1024) /* cycle data in header */
#define XLOG_RECORD_BSHIFT 14 /* 16384 == 1 << 14 */
#define XLOG_MIN_RECORD_BSHIFT 14 /* 16384 == 1 << 14 */
#define XLOG_BIG_RECORD_BSHIFT 15 /* 32k == 1 << 15 */
#define XLOG_MAX_RECORD_BSHIFT 18 /* 256k == 1 << 18 */
#define XLOG_BTOLSUNIT(log, b) (((b)+(log)->l_mp->m_sb.sb_logsunit-1) / \
@ -250,22 +249,6 @@ typedef __uint32_t xlog_tid_t;
/* Ticket reservation region accounting */
#define XLOG_TIC_LEN_MAX 15
#define XLOG_TIC_RESET_RES(t) ((t)->t_res_num = \
(t)->t_res_arr_sum = (t)->t_res_num_ophdrs = 0)
#define XLOG_TIC_ADD_OPHDR(t) ((t)->t_res_num_ophdrs++)
#define XLOG_TIC_ADD_REGION(t, len, type) \
do { \
if ((t)->t_res_num == XLOG_TIC_LEN_MAX) { \
/* add to overflow and start again */ \
(t)->t_res_o_flow += (t)->t_res_arr_sum; \
(t)->t_res_num = 0; \
(t)->t_res_arr_sum = 0; \
} \
(t)->t_res_arr[(t)->t_res_num].r_len = (len); \
(t)->t_res_arr[(t)->t_res_num].r_type = (type); \
(t)->t_res_arr_sum += (len); \
(t)->t_res_num++; \
} while (0)
/*
* Reservation region

View file

@ -2245,7 +2245,7 @@ xlog_recover_do_inode_trans(
int error;
int attr_index;
uint fields;
xfs_dinode_core_t *dicp;
xfs_icdinode_t *dicp;
int need_free = 0;
if (pass == XLOG_RECOVER_PASS1) {
@ -2309,7 +2309,7 @@ xlog_recover_do_inode_trans(
* Make sure the place we're flushing out to really looks
* like an inode!
*/
if (unlikely(INT_GET(dip->di_core.di_magic, ARCH_CONVERT) != XFS_DINODE_MAGIC)) {
if (unlikely(be16_to_cpu(dip->di_core.di_magic) != XFS_DINODE_MAGIC)) {
xfs_buf_relse(bp);
xfs_fs_cmn_err(CE_ALERT, mp,
"xfs_inode_recover: Bad inode magic number, dino ptr = 0x%p, dino bp = 0x%p, ino = %Ld",
@ -2319,7 +2319,7 @@ xlog_recover_do_inode_trans(
error = EFSCORRUPTED;
goto error;
}
dicp = (xfs_dinode_core_t*)(item->ri_buf[1].i_addr);
dicp = (xfs_icdinode_t *)(item->ri_buf[1].i_addr);
if (unlikely(dicp->di_magic != XFS_DINODE_MAGIC)) {
xfs_buf_relse(bp);
xfs_fs_cmn_err(CE_ALERT, mp,
@ -2332,15 +2332,13 @@ xlog_recover_do_inode_trans(
}
/* Skip replay when the on disk inode is newer than the log one */
if (dicp->di_flushiter <
INT_GET(dip->di_core.di_flushiter, ARCH_CONVERT)) {
if (dicp->di_flushiter < be16_to_cpu(dip->di_core.di_flushiter)) {
/*
* Deal with the wrap case, DI_MAX_FLUSH is less
* than smaller numbers
*/
if ((INT_GET(dip->di_core.di_flushiter, ARCH_CONVERT)
== DI_MAX_FLUSH) &&
(dicp->di_flushiter < (DI_MAX_FLUSH>>1))) {
if (be16_to_cpu(dip->di_core.di_flushiter) == DI_MAX_FLUSH &&
dicp->di_flushiter < (DI_MAX_FLUSH >> 1)) {
/* do nothing */
} else {
xfs_buf_relse(bp);
@ -2411,8 +2409,8 @@ xlog_recover_do_inode_trans(
}
/* The core is in in-core format */
xfs_xlate_dinode_core((xfs_caddr_t)&dip->di_core,
(xfs_dinode_core_t*)item->ri_buf[1].i_addr, -1);
xfs_dinode_to_disk(&dip->di_core,
(xfs_icdinode_t *)item->ri_buf[1].i_addr);
/* the rest is in on-disk format */
if (item->ri_buf[1].i_len > sizeof(xfs_dinode_core_t)) {
@ -2424,8 +2422,7 @@ xlog_recover_do_inode_trans(
fields = in_f->ilf_fields;
switch (fields & (XFS_ILOG_DEV | XFS_ILOG_UUID)) {
case XFS_ILOG_DEV:
INT_SET(dip->di_u.di_dev, ARCH_CONVERT, in_f->ilf_u.ilfu_rdev);
dip->di_u.di_dev = cpu_to_be32(in_f->ilf_u.ilfu_rdev);
break;
case XFS_ILOG_UUID:
dip->di_u.di_muuid = in_f->ilf_u.ilfu_uuid;
@ -3234,8 +3231,8 @@ xlog_recover_process_iunlinks(
ASSERT(ip->i_d.di_nlink == 0);
/* setup for the next pass */
agino = INT_GET(dip->di_next_unlinked,
ARCH_CONVERT);
agino = be32_to_cpu(
dip->di_next_unlinked);
xfs_buf_relse(ibp);
/*
* Prevent any DMAPI event from
@ -3837,7 +3834,10 @@ xlog_do_recover(
*/
bp = xfs_getsb(log->l_mp, 0);
XFS_BUF_UNDONE(bp);
ASSERT(!(XFS_BUF_ISWRITE(bp)));
ASSERT(!(XFS_BUF_ISDELAYWRITE(bp)));
XFS_BUF_READ(bp);
XFS_BUF_UNASYNC(bp);
xfsbdstrat(log->l_mp, bp);
if ((error = xfs_iowait(bp))) {
xfs_ioerror_alert("xlog_do_recover",
@ -3849,7 +3849,7 @@ xlog_do_recover(
/* Convert superblock from on-disk format */
sbp = &log->l_mp->m_sb;
xfs_xlatesb(XFS_BUF_TO_SBP(bp), sbp, 1, XFS_SB_ALL_BITS);
xfs_sb_from_disk(sbp, XFS_BUF_TO_SBP(bp));
ASSERT(sbp->sb_magicnum == XFS_SB_MAGIC);
ASSERT(XFS_SB_GOOD_VERSION(sbp));
xfs_buf_relse(bp);
@ -4027,7 +4027,7 @@ xlog_recover_check_summary(
sbbp = xfs_getsb(mp, 0);
#ifdef XFS_LOUD_RECOVERY
sbp = &mp->m_sb;
xfs_xlatesb(XFS_BUF_TO_SBP(sbbp), sbp, 1, XFS_SB_ALL_BITS);
xfs_sb_from_disk(sbp, XFS_BUF_TO_SBP(sbbp));
cmn_err(CE_NOTE,
"xlog_recover_check_summary: sb_icount %Lu itotal %Lu",
sbp->sb_icount, itotal);

View file

@ -139,7 +139,7 @@ xfs_mount_init(void)
AIL_LOCKINIT(&mp->m_ail_lock, "xfs_ail");
spinlock_init(&mp->m_sb_lock, "xfs_sb");
mutex_init(&mp->m_ilock);
initnsema(&mp->m_growlock, 1, "xfs_grow");
mutex_init(&mp->m_growlock);
/*
* Initialize the AIL.
*/
@ -157,14 +157,8 @@ xfs_mount_init(void)
*/
void
xfs_mount_free(
xfs_mount_t *mp,
int remove_bhv)
xfs_mount_t *mp)
{
if (mp->m_ihash)
xfs_ihash_free(mp);
if (mp->m_chash)
xfs_chash_free(mp);
if (mp->m_perag) {
int agno;
@ -180,7 +174,7 @@ xfs_mount_free(
AIL_LOCK_DESTROY(&mp->m_ail_lock);
spinlock_destroy(&mp->m_sb_lock);
mutex_destroy(&mp->m_ilock);
freesema(&mp->m_growlock);
mutex_destroy(&mp->m_growlock);
if (mp->m_quotainfo)
XFS_QM_DONE(mp);
@ -191,15 +185,7 @@ xfs_mount_free(
if (mp->m_logname != NULL)
kmem_free(mp->m_logname, strlen(mp->m_logname) + 1);
if (remove_bhv) {
struct bhv_vfs *vfsp = XFS_MTOVFS(mp);
bhv_remove_all_vfsops(vfsp, 0);
VFS_REMOVEBHV(vfsp, &mp->m_bhv);
}
xfs_icsb_destroy_counters(mp);
kmem_free(mp, sizeof(xfs_mount_t));
}
/*
@ -342,9 +328,19 @@ xfs_mount_validate_sb(
return 0;
}
STATIC void
xfs_initialize_perag_icache(
xfs_perag_t *pag)
{
if (!pag->pag_ici_init) {
rwlock_init(&pag->pag_ici_lock);
INIT_RADIX_TREE(&pag->pag_ici_root, GFP_ATOMIC);
pag->pag_ici_init = 1;
}
}
xfs_agnumber_t
xfs_initialize_perag(
bhv_vfs_t *vfs,
xfs_mount_t *mp,
xfs_agnumber_t agcount)
{
@ -362,7 +358,7 @@ xfs_initialize_perag(
/* Clear the mount flag if no inode can overflow 32 bits
* on this filesystem, or if specifically requested..
*/
if ((vfs->vfs_flag & VFS_32BITINODES) && ino > max_inum) {
if ((mp->m_flags & XFS_MOUNT_SMALL_INUMS) && ino > max_inum) {
mp->m_flags |= XFS_MOUNT_32BITINODES;
} else {
mp->m_flags &= ~XFS_MOUNT_32BITINODES;
@ -396,48 +392,92 @@ xfs_initialize_perag(
pag->pagi_inodeok = 1;
if (index < max_metadata)
pag->pagf_metadata = 1;
xfs_initialize_perag_icache(pag);
}
} else {
/* Setup default behavior for smaller filesystems */
for (index = 0; index < agcount; index++) {
pag = &mp->m_perag[index];
pag->pagi_inodeok = 1;
xfs_initialize_perag_icache(pag);
}
}
return index;
}
void
xfs_sb_from_disk(
xfs_sb_t *to,
xfs_dsb_t *from)
{
to->sb_magicnum = be32_to_cpu(from->sb_magicnum);
to->sb_blocksize = be32_to_cpu(from->sb_blocksize);
to->sb_dblocks = be64_to_cpu(from->sb_dblocks);
to->sb_rblocks = be64_to_cpu(from->sb_rblocks);
to->sb_rextents = be64_to_cpu(from->sb_rextents);
memcpy(&to->sb_uuid, &from->sb_uuid, sizeof(to->sb_uuid));
to->sb_logstart = be64_to_cpu(from->sb_logstart);
to->sb_rootino = be64_to_cpu(from->sb_rootino);
to->sb_rbmino = be64_to_cpu(from->sb_rbmino);
to->sb_rsumino = be64_to_cpu(from->sb_rsumino);
to->sb_rextsize = be32_to_cpu(from->sb_rextsize);
to->sb_agblocks = be32_to_cpu(from->sb_agblocks);
to->sb_agcount = be32_to_cpu(from->sb_agcount);
to->sb_rbmblocks = be32_to_cpu(from->sb_rbmblocks);
to->sb_logblocks = be32_to_cpu(from->sb_logblocks);
to->sb_versionnum = be16_to_cpu(from->sb_versionnum);
to->sb_sectsize = be16_to_cpu(from->sb_sectsize);
to->sb_inodesize = be16_to_cpu(from->sb_inodesize);
to->sb_inopblock = be16_to_cpu(from->sb_inopblock);
memcpy(&to->sb_fname, &from->sb_fname, sizeof(to->sb_fname));
to->sb_blocklog = from->sb_blocklog;
to->sb_sectlog = from->sb_sectlog;
to->sb_inodelog = from->sb_inodelog;
to->sb_inopblog = from->sb_inopblog;
to->sb_agblklog = from->sb_agblklog;
to->sb_rextslog = from->sb_rextslog;
to->sb_inprogress = from->sb_inprogress;
to->sb_imax_pct = from->sb_imax_pct;
to->sb_icount = be64_to_cpu(from->sb_icount);
to->sb_ifree = be64_to_cpu(from->sb_ifree);
to->sb_fdblocks = be64_to_cpu(from->sb_fdblocks);
to->sb_frextents = be64_to_cpu(from->sb_frextents);
to->sb_uquotino = be64_to_cpu(from->sb_uquotino);
to->sb_gquotino = be64_to_cpu(from->sb_gquotino);
to->sb_qflags = be16_to_cpu(from->sb_qflags);
to->sb_flags = from->sb_flags;
to->sb_shared_vn = from->sb_shared_vn;
to->sb_inoalignmt = be32_to_cpu(from->sb_inoalignmt);
to->sb_unit = be32_to_cpu(from->sb_unit);
to->sb_width = be32_to_cpu(from->sb_width);
to->sb_dirblklog = from->sb_dirblklog;
to->sb_logsectlog = from->sb_logsectlog;
to->sb_logsectsize = be16_to_cpu(from->sb_logsectsize);
to->sb_logsunit = be32_to_cpu(from->sb_logsunit);
to->sb_features2 = be32_to_cpu(from->sb_features2);
}
/*
* xfs_xlatesb
* Copy in core superblock to ondisk one.
*
* data - on disk version of sb
* sb - a superblock
* dir - conversion direction: <0 - convert sb to buf
* >0 - convert buf to sb
* fields - which fields to copy (bitmask)
* The fields argument is mask of superblock fields to copy.
*/
void
xfs_xlatesb(
void *data,
xfs_sb_t *sb,
int dir,
xfs_sb_to_disk(
xfs_dsb_t *to,
xfs_sb_t *from,
__int64_t fields)
{
xfs_caddr_t buf_ptr;
xfs_caddr_t mem_ptr;
xfs_caddr_t to_ptr = (xfs_caddr_t)to;
xfs_caddr_t from_ptr = (xfs_caddr_t)from;
xfs_sb_field_t f;
int first;
int size;
ASSERT(dir);
ASSERT(fields);
if (!fields)
return;
buf_ptr = (xfs_caddr_t)data;
mem_ptr = (xfs_caddr_t)sb;
while (fields) {
f = (xfs_sb_field_t)xfs_lowbit64((__uint64_t)fields);
first = xfs_sb_info[f].offset;
@ -446,26 +486,20 @@ xfs_xlatesb(
ASSERT(xfs_sb_info[f].type == 0 || xfs_sb_info[f].type == 1);
if (size == 1 || xfs_sb_info[f].type == 1) {
if (dir > 0) {
memcpy(mem_ptr + first, buf_ptr + first, size);
} else {
memcpy(buf_ptr + first, mem_ptr + first, size);
}
memcpy(to_ptr + first, from_ptr + first, size);
} else {
switch (size) {
case 2:
INT_XLATE(*(__uint16_t*)(buf_ptr+first),
*(__uint16_t*)(mem_ptr+first),
dir, ARCH_CONVERT);
*(__be16 *)(to_ptr + first) =
cpu_to_be16(*(__u16 *)(from_ptr + first));
break;
case 4:
INT_XLATE(*(__uint32_t*)(buf_ptr+first),
*(__uint32_t*)(mem_ptr+first),
dir, ARCH_CONVERT);
*(__be32 *)(to_ptr + first) =
cpu_to_be32(*(__u32 *)(from_ptr + first));
break;
case 8:
INT_XLATE(*(__uint64_t*)(buf_ptr+first),
*(__uint64_t*)(mem_ptr+first), dir, ARCH_CONVERT);
*(__be64 *)(to_ptr + first) =
cpu_to_be64(*(__u64 *)(from_ptr + first));
break;
default:
ASSERT(0);
@ -487,7 +521,6 @@ xfs_readsb(xfs_mount_t *mp, int flags)
unsigned int sector_size;
unsigned int extra_flags;
xfs_buf_t *bp;
xfs_sb_t *sbp;
int error;
ASSERT(mp->m_sb_bp == NULL);
@ -515,8 +548,7 @@ xfs_readsb(xfs_mount_t *mp, int flags)
* Initialize the mount structure from the superblock.
* But first do some basic consistency checking.
*/
sbp = XFS_BUF_TO_SBP(bp);
xfs_xlatesb(XFS_BUF_PTR(bp), &(mp->m_sb), 1, XFS_SB_ALL_BITS);
xfs_sb_from_disk(&mp->m_sb, XFS_BUF_TO_SBP(bp));
error = xfs_mount_validate_sb(mp, &(mp->m_sb), flags);
if (error) {
@ -715,7 +747,6 @@ xfs_initialize_perag_data(xfs_mount_t *mp, xfs_agnumber_t agcount)
*/
int
xfs_mountfs(
bhv_vfs_t *vfsp,
xfs_mount_t *mp,
int mfsi_flags)
{
@ -842,14 +873,11 @@ xfs_mountfs(
*/
if ((mfsi_flags & XFS_MFSI_SECOND) == 0 &&
(mp->m_flags & XFS_MOUNT_NOUUID) == 0) {
__uint64_t ret64;
if (xfs_uuid_mount(mp)) {
error = XFS_ERROR(EINVAL);
goto error1;
}
uuid_mounted=1;
ret64 = uuid_hash64(&sbp->sb_uuid);
memcpy(&vfsp->vfs_fsid, &ret64, sizeof(ret64));
}
/*
@ -871,16 +899,6 @@ xfs_mountfs(
writeio_log = mp->m_writeio_log;
}
/*
* Set the number of readahead buffers to use based on
* physical memory size.
*/
if (xfs_physmem <= 4096) /* <= 16MB */
mp->m_nreadaheads = XFS_RW_NREADAHEAD_16MB;
else if (xfs_physmem <= 8192) /* <= 32MB */
mp->m_nreadaheads = XFS_RW_NREADAHEAD_32MB;
else
mp->m_nreadaheads = XFS_RW_NREADAHEAD_K32;
if (sbp->sb_blocklog > readio_log) {
mp->m_readio_log = sbp->sb_blocklog;
} else {
@ -895,15 +913,12 @@ xfs_mountfs(
mp->m_writeio_blocks = 1 << (mp->m_writeio_log - sbp->sb_blocklog);
/*
* Set the inode cluster size based on the physical memory
* size. This may still be overridden by the file system
* Set the inode cluster size.
* This may still be overridden by the file system
* block size if it is larger than the chosen cluster size.
*/
if (xfs_physmem <= btoc(32 * 1024 * 1024)) { /* <= 32 MB */
mp->m_inode_cluster_size = XFS_INODE_SMALL_CLUSTER_SIZE;
} else {
mp->m_inode_cluster_size = XFS_INODE_BIG_CLUSTER_SIZE;
}
mp->m_inode_cluster_size = XFS_INODE_BIG_CLUSTER_SIZE;
/*
* Set whether we're using inode alignment.
*/
@ -987,16 +1002,6 @@ xfs_mountfs(
*/
uuid_getnodeuniq(&sbp->sb_uuid, mp->m_fixedfsid);
/*
* The vfs structure needs to have a file system independent
* way of checking for the invariant file system ID. Since it
* can't look at mount structures it has a pointer to the data
* in the mount structure.
*
* File systems that don't support user level file handles (i.e.
* all of them except for XFS) will leave vfs_altfsid as NULL.
*/
vfsp->vfs_altfsid = (xfs_fsid_t *)mp->m_fixedfsid;
mp->m_dmevmask = 0; /* not persistent; set after each mount */
xfs_dir_mount(mp);
@ -1011,13 +1016,6 @@ xfs_mountfs(
*/
xfs_trans_init(mp);
/*
* Allocate and initialize the inode hash table for this
* file system.
*/
xfs_ihash_init(mp);
xfs_chash_init(mp);
/*
* Allocate and initialize the per-ag data.
*/
@ -1025,7 +1023,7 @@ xfs_mountfs(
mp->m_perag =
kmem_zalloc(sbp->sb_agcount * sizeof(xfs_perag_t), KM_SLEEP);
mp->m_maxagi = xfs_initialize_perag(vfsp, mp, sbp->sb_agcount);
mp->m_maxagi = xfs_initialize_perag(mp, sbp->sb_agcount);
/*
* log's mount-time initialization. Perform 1st part recovery if needed
@ -1116,7 +1114,7 @@ xfs_mountfs(
* If fs is not mounted readonly, then update the superblock
* unit and width changes.
*/
if (update_flags && !(vfsp->vfs_flag & VFS_RDONLY))
if (update_flags && !(mp->m_flags & XFS_MOUNT_RDONLY))
xfs_mount_log_sbunit(mp, update_flags);
/*
@ -1169,8 +1167,6 @@ xfs_mountfs(
error3:
xfs_log_unmount_dealloc(mp);
error2:
xfs_ihash_free(mp);
xfs_chash_free(mp);
for (agno = 0; agno < sbp->sb_agcount; agno++)
if (mp->m_perag[agno].pagb_list)
kmem_free(mp->m_perag[agno].pagb_list,
@ -1194,10 +1190,6 @@ xfs_mountfs(
int
xfs_unmountfs(xfs_mount_t *mp, struct cred *cr)
{
struct bhv_vfs *vfsp = XFS_MTOVFS(mp);
#if defined(DEBUG) || defined(INDUCE_IO_ERROR)
int64_t fsid;
#endif
__uint64_t resblks;
/*
@ -1261,21 +1253,17 @@ xfs_unmountfs(xfs_mount_t *mp, struct cred *cr)
xfs_uuid_unmount(mp);
#if defined(DEBUG) || defined(INDUCE_IO_ERROR)
/*
* clear all error tags on this filesystem
*/
memcpy(&fsid, &vfsp->vfs_fsid, sizeof(int64_t));
xfs_errortag_clearall_umount(fsid, mp->m_fsname, 0);
xfs_errortag_clearall(mp, 0);
#endif
XFS_IODONE(vfsp);
xfs_mount_free(mp, 1);
XFS_IODONE(mp);
xfs_mount_free(mp);
return 0;
}
void
xfs_unmountfs_close(xfs_mount_t *mp, struct cred *cr)
{
if (mp->m_logdev_targp != mp->m_ddev_targp)
if (mp->m_logdev_targp && mp->m_logdev_targp != mp->m_ddev_targp)
xfs_free_buftarg(mp->m_logdev_targp, 1);
if (mp->m_rtdev_targp)
xfs_free_buftarg(mp->m_rtdev_targp, 1);
@ -1295,10 +1283,8 @@ xfs_unmountfs_wait(xfs_mount_t *mp)
int
xfs_fs_writable(xfs_mount_t *mp)
{
bhv_vfs_t *vfsp = XFS_MTOVFS(mp);
return !(vfs_test_for_freeze(vfsp) || XFS_FORCED_SHUTDOWN(mp) ||
(vfsp->vfs_flag & VFS_RDONLY));
return !(xfs_test_for_freeze(mp) || XFS_FORCED_SHUTDOWN(mp) ||
(mp->m_flags & XFS_MOUNT_RDONLY));
}
/*
@ -1348,34 +1334,44 @@ xfs_log_sbcount(
return 0;
}
STATIC void
xfs_mark_shared_ro(
xfs_mount_t *mp,
xfs_buf_t *bp)
{
xfs_dsb_t *sb = XFS_BUF_TO_SBP(bp);
__uint16_t version;
if (!(sb->sb_flags & XFS_SBF_READONLY))
sb->sb_flags |= XFS_SBF_READONLY;
version = be16_to_cpu(sb->sb_versionnum);
if ((version & XFS_SB_VERSION_NUMBITS) != XFS_SB_VERSION_4 ||
!(version & XFS_SB_VERSION_SHAREDBIT))
version |= XFS_SB_VERSION_SHAREDBIT;
sb->sb_versionnum = cpu_to_be16(version);
}
int
xfs_unmountfs_writesb(xfs_mount_t *mp)
{
xfs_buf_t *sbp;
xfs_sb_t *sb;
int error = 0;
/*
* skip superblock write if fs is read-only, or
* if we are doing a forced umount.
*/
if (!(XFS_MTOVFS(mp)->vfs_flag & VFS_RDONLY ||
if (!((mp->m_flags & XFS_MOUNT_RDONLY) ||
XFS_FORCED_SHUTDOWN(mp))) {
sbp = xfs_getsb(mp, 0);
sb = XFS_BUF_TO_SBP(sbp);
/*
* mark shared-readonly if desired
*/
if (mp->m_mk_sharedro) {
if (!(sb->sb_flags & XFS_SBF_READONLY))
sb->sb_flags |= XFS_SBF_READONLY;
if (!XFS_SB_VERSION_HASSHARED(sb))
XFS_SB_VERSION_ADDSHARED(sb);
xfs_fs_cmn_err(CE_NOTE, mp,
"Unmounting, marking shared read-only");
}
if (mp->m_mk_sharedro)
xfs_mark_shared_ro(mp, sbp);
XFS_BUF_UNDONE(sbp);
XFS_BUF_UNREAD(sbp);
@ -1410,7 +1406,6 @@ xfs_mod_sb(xfs_trans_t *tp, __int64_t fields)
int first;
int last;
xfs_mount_t *mp;
xfs_sb_t *sbp;
xfs_sb_field_t f;
ASSERT(fields);
@ -1418,13 +1413,12 @@ xfs_mod_sb(xfs_trans_t *tp, __int64_t fields)
return;
mp = tp->t_mountp;
bp = xfs_trans_getsb(tp, mp, 0);
sbp = XFS_BUF_TO_SBP(bp);
first = sizeof(xfs_sb_t);
last = 0;
/* translate/copy */
xfs_xlatesb(XFS_BUF_PTR(bp), &(mp->m_sb), -1, fields);
xfs_sb_to_disk(XFS_BUF_TO_SBP(bp), &mp->m_sb, fields);
/* find modified range */

View file

@ -54,13 +54,8 @@ typedef struct xfs_trans_reservations {
#else
struct cred;
struct log;
struct bhv_vfs;
struct bhv_vnode;
struct xfs_mount_args;
struct xfs_ihash;
struct xfs_chash;
struct xfs_inode;
struct xfs_perag;
struct xfs_iocore;
struct xfs_bmbt_irec;
struct xfs_bmap_free;
@ -68,9 +63,6 @@ struct xfs_extdelta;
struct xfs_swapext;
struct xfs_mru_cache;
extern struct bhv_vfsops xfs_vfsops;
extern struct bhv_vnodeops xfs_vnodeops;
#define AIL_LOCK_T lock_t
#define AIL_LOCKINIT(x,y) spinlock_init(x,y)
#define AIL_LOCK_DESTROY(x) spinlock_destroy(x)
@ -82,15 +74,17 @@ extern struct bhv_vnodeops xfs_vnodeops;
* Prototypes and functions for the Data Migration subsystem.
*/
typedef int (*xfs_send_data_t)(int, struct bhv_vnode *,
typedef int (*xfs_send_data_t)(int, bhv_vnode_t *,
xfs_off_t, size_t, int, bhv_vrwlock_t *);
typedef int (*xfs_send_mmap_t)(struct vm_area_struct *, uint);
typedef int (*xfs_send_destroy_t)(struct bhv_vnode *, dm_right_t);
typedef int (*xfs_send_namesp_t)(dm_eventtype_t, struct bhv_vfs *,
struct bhv_vnode *,
dm_right_t, struct bhv_vnode *, dm_right_t,
typedef int (*xfs_send_destroy_t)(bhv_vnode_t *, dm_right_t);
typedef int (*xfs_send_namesp_t)(dm_eventtype_t, struct xfs_mount *,
bhv_vnode_t *,
dm_right_t, bhv_vnode_t *, dm_right_t,
char *, char *, mode_t, int, int);
typedef void (*xfs_send_unmount_t)(struct bhv_vfs *, struct bhv_vnode *,
typedef int (*xfs_send_mount_t)(struct xfs_mount *, dm_right_t,
char *, char *);
typedef void (*xfs_send_unmount_t)(struct xfs_mount *, bhv_vnode_t *,
dm_right_t, mode_t, int, int);
typedef struct xfs_dmops {
@ -98,21 +92,24 @@ typedef struct xfs_dmops {
xfs_send_mmap_t xfs_send_mmap;
xfs_send_destroy_t xfs_send_destroy;
xfs_send_namesp_t xfs_send_namesp;
xfs_send_mount_t xfs_send_mount;
xfs_send_unmount_t xfs_send_unmount;
} xfs_dmops_t;
#define XFS_SEND_DATA(mp, ev,vp,off,len,fl,lock) \
(*(mp)->m_dm_ops.xfs_send_data)(ev,vp,off,len,fl,lock)
(*(mp)->m_dm_ops->xfs_send_data)(ev,vp,off,len,fl,lock)
#define XFS_SEND_MMAP(mp, vma,fl) \
(*(mp)->m_dm_ops.xfs_send_mmap)(vma,fl)
(*(mp)->m_dm_ops->xfs_send_mmap)(vma,fl)
#define XFS_SEND_DESTROY(mp, vp,right) \
(*(mp)->m_dm_ops.xfs_send_destroy)(vp,right)
(*(mp)->m_dm_ops->xfs_send_destroy)(vp,right)
#define XFS_SEND_NAMESP(mp, ev,b1,r1,b2,r2,n1,n2,mode,rval,fl) \
(*(mp)->m_dm_ops.xfs_send_namesp)(ev,NULL,b1,r1,b2,r2,n1,n2,mode,rval,fl)
#define XFS_SEND_PREUNMOUNT(mp, vfs,b1,r1,b2,r2,n1,n2,mode,rval,fl) \
(*(mp)->m_dm_ops.xfs_send_namesp)(DM_EVENT_PREUNMOUNT,vfs,b1,r1,b2,r2,n1,n2,mode,rval,fl)
#define XFS_SEND_UNMOUNT(mp, vfsp,vp,right,mode,rval,fl) \
(*(mp)->m_dm_ops.xfs_send_unmount)(vfsp,vp,right,mode,rval,fl)
(*(mp)->m_dm_ops->xfs_send_namesp)(ev,NULL,b1,r1,b2,r2,n1,n2,mode,rval,fl)
#define XFS_SEND_PREUNMOUNT(mp,b1,r1,b2,r2,n1,n2,mode,rval,fl) \
(*(mp)->m_dm_ops->xfs_send_namesp)(DM_EVENT_PREUNMOUNT,mp,b1,r1,b2,r2,n1,n2,mode,rval,fl)
#define XFS_SEND_MOUNT(mp,right,path,name) \
(*(mp)->m_dm_ops->xfs_send_mount)(mp,right,path,name)
#define XFS_SEND_UNMOUNT(mp, vp,right,mode,rval,fl) \
(*(mp)->m_dm_ops->xfs_send_unmount)(mp,vp,right,mode,rval,fl)
/*
@ -142,6 +139,9 @@ typedef struct xfs_dquot * (*xfs_dqvopchown_t)(
struct xfs_dquot **, struct xfs_dquot *);
typedef int (*xfs_dqvopchownresv_t)(struct xfs_trans *, struct xfs_inode *,
struct xfs_dquot *, struct xfs_dquot *, uint);
typedef void (*xfs_dqstatvfs_t)(struct xfs_inode *, bhv_statvfs_t *);
typedef int (*xfs_dqsync_t)(struct xfs_mount *, int flags);
typedef int (*xfs_quotactl_t)(struct xfs_mount *, int, int, xfs_caddr_t);
typedef struct xfs_qmops {
xfs_qminit_t xfs_qminit;
@ -157,42 +157,51 @@ typedef struct xfs_qmops {
xfs_dqvoprename_t xfs_dqvoprename;
xfs_dqvopchown_t xfs_dqvopchown;
xfs_dqvopchownresv_t xfs_dqvopchownresv;
xfs_dqstatvfs_t xfs_dqstatvfs;
xfs_dqsync_t xfs_dqsync;
xfs_quotactl_t xfs_quotactl;
struct xfs_dqtrxops *xfs_dqtrxops;
} xfs_qmops_t;
#define XFS_QM_INIT(mp, mnt, fl) \
(*(mp)->m_qm_ops.xfs_qminit)(mp, mnt, fl)
(*(mp)->m_qm_ops->xfs_qminit)(mp, mnt, fl)
#define XFS_QM_MOUNT(mp, mnt, fl, mfsi_flags) \
(*(mp)->m_qm_ops.xfs_qmmount)(mp, mnt, fl, mfsi_flags)
(*(mp)->m_qm_ops->xfs_qmmount)(mp, mnt, fl, mfsi_flags)
#define XFS_QM_UNMOUNT(mp) \
(*(mp)->m_qm_ops.xfs_qmunmount)(mp)
(*(mp)->m_qm_ops->xfs_qmunmount)(mp)
#define XFS_QM_DONE(mp) \
(*(mp)->m_qm_ops.xfs_qmdone)(mp)
(*(mp)->m_qm_ops->xfs_qmdone)(mp)
#define XFS_QM_DQRELE(mp, dq) \
(*(mp)->m_qm_ops.xfs_dqrele)(dq)
(*(mp)->m_qm_ops->xfs_dqrele)(dq)
#define XFS_QM_DQATTACH(mp, ip, fl) \
(*(mp)->m_qm_ops.xfs_dqattach)(ip, fl)
(*(mp)->m_qm_ops->xfs_dqattach)(ip, fl)
#define XFS_QM_DQDETACH(mp, ip) \
(*(mp)->m_qm_ops.xfs_dqdetach)(ip)
(*(mp)->m_qm_ops->xfs_dqdetach)(ip)
#define XFS_QM_DQPURGEALL(mp, fl) \
(*(mp)->m_qm_ops.xfs_dqpurgeall)(mp, fl)
(*(mp)->m_qm_ops->xfs_dqpurgeall)(mp, fl)
#define XFS_QM_DQVOPALLOC(mp, ip, uid, gid, prid, fl, dq1, dq2) \
(*(mp)->m_qm_ops.xfs_dqvopalloc)(mp, ip, uid, gid, prid, fl, dq1, dq2)
(*(mp)->m_qm_ops->xfs_dqvopalloc)(mp, ip, uid, gid, prid, fl, dq1, dq2)
#define XFS_QM_DQVOPCREATE(mp, tp, ip, dq1, dq2) \
(*(mp)->m_qm_ops.xfs_dqvopcreate)(tp, ip, dq1, dq2)
(*(mp)->m_qm_ops->xfs_dqvopcreate)(tp, ip, dq1, dq2)
#define XFS_QM_DQVOPRENAME(mp, ip) \
(*(mp)->m_qm_ops.xfs_dqvoprename)(ip)
(*(mp)->m_qm_ops->xfs_dqvoprename)(ip)
#define XFS_QM_DQVOPCHOWN(mp, tp, ip, dqp, dq) \
(*(mp)->m_qm_ops.xfs_dqvopchown)(tp, ip, dqp, dq)
(*(mp)->m_qm_ops->xfs_dqvopchown)(tp, ip, dqp, dq)
#define XFS_QM_DQVOPCHOWNRESV(mp, tp, ip, dq1, dq2, fl) \
(*(mp)->m_qm_ops.xfs_dqvopchownresv)(tp, ip, dq1, dq2, fl)
(*(mp)->m_qm_ops->xfs_dqvopchownresv)(tp, ip, dq1, dq2, fl)
#define XFS_QM_DQSTATVFS(ip, statp) \
(*(ip)->i_mount->m_qm_ops->xfs_dqstatvfs)(ip, statp)
#define XFS_QM_DQSYNC(mp, flags) \
(*(mp)->m_qm_ops->xfs_dqsync)(mp, flags)
#define XFS_QM_QUOTACTL(mp, cmd, id, addr) \
(*(mp)->m_qm_ops->xfs_quotactl)(mp, cmd, id, addr)
/*
* Prototypes and functions for I/O core modularization.
*/
typedef int (*xfs_ioinit_t)(struct bhv_vfs *,
typedef int (*xfs_ioinit_t)(struct xfs_mount *,
struct xfs_mount_args *, int);
typedef int (*xfs_bmapi_t)(struct xfs_trans *, void *,
xfs_fileoff_t, xfs_filblks_t, int,
@ -222,7 +231,7 @@ typedef void (*xfs_lock_demote_t)(void *, uint);
typedef int (*xfs_lock_nowait_t)(void *, uint);
typedef void (*xfs_unlk_t)(void *, unsigned int);
typedef xfs_fsize_t (*xfs_size_t)(void *);
typedef xfs_fsize_t (*xfs_iodone_t)(struct bhv_vfs *);
typedef xfs_fsize_t (*xfs_iodone_t)(struct xfs_mount *);
typedef int (*xfs_swap_extents_t)(void *, void *,
struct xfs_swapext*);
@ -245,8 +254,8 @@ typedef struct xfs_ioops {
xfs_swap_extents_t xfs_swap_extents_func;
} xfs_ioops_t;
#define XFS_IOINIT(vfsp, args, flags) \
(*(mp)->m_io_ops.xfs_ioinit)(vfsp, args, flags)
#define XFS_IOINIT(mp, args, flags) \
(*(mp)->m_io_ops.xfs_ioinit)(mp, args, flags)
#define XFS_BMAPI(mp, trans,io,bno,len,f,first,tot,mval,nmap,flist,delta) \
(*(mp)->m_io_ops.xfs_bmapi_func) \
(trans,(io)->io_obj,bno,len,f,first,tot,mval,nmap,flist,delta)
@ -280,8 +289,8 @@ typedef struct xfs_ioops {
(*(mp)->m_io_ops.xfs_ilock_demote)((io)->io_obj, mode)
#define XFS_SIZE(mp, io) \
(*(mp)->m_io_ops.xfs_size_func)((io)->io_obj)
#define XFS_IODONE(vfsp) \
(*(mp)->m_io_ops.xfs_iodone)(vfsp)
#define XFS_IODONE(mp) \
(*(mp)->m_io_ops.xfs_iodone)(mp)
#define XFS_SWAP_EXTENTS(mp, io, tio, sxp) \
(*(mp)->m_io_ops.xfs_swap_extents_func) \
((io)->io_obj, (tio)->io_obj, sxp)
@ -318,7 +327,7 @@ extern void xfs_icsb_sync_counters_flags(struct xfs_mount *, int);
#endif
typedef struct xfs_mount {
bhv_desc_t m_bhv; /* vfs xfs behavior */
struct super_block *m_super;
xfs_tid_t m_tid; /* next unused tid for fs */
AIL_LOCK_T m_ail_lock; /* fs AIL mutex */
xfs_ail_entry_t m_ail; /* fs active log item list */
@ -335,8 +344,6 @@ typedef struct xfs_mount {
xfs_agnumber_t m_agirotor; /* last ag dir inode alloced */
lock_t m_agirotor_lock;/* .. and lock protecting it */
xfs_agnumber_t m_maxagi; /* highest inode alloc group */
size_t m_ihsize; /* size of next field */
struct xfs_ihash *m_ihash; /* fs private inode hash table*/
struct xfs_inode *m_inodes; /* active inode list */
struct list_head m_del_inodes; /* inodes to reclaim */
mutex_t m_ilock; /* inode list mutex */
@ -362,7 +369,6 @@ typedef struct xfs_mount {
__uint8_t m_blkbb_log; /* blocklog - BBSHIFT */
__uint8_t m_agno_log; /* log #ag's */
__uint8_t m_agino_log; /* #bits for agino in inum */
__uint8_t m_nreadaheads; /* #readahead buffers */
__uint16_t m_inode_cluster_size;/* min inode buf size */
uint m_blockmask; /* sb_blocksize-1 */
uint m_blockwsize; /* sb_blocksize in words */
@ -378,7 +384,7 @@ typedef struct xfs_mount {
uint m_in_maxlevels; /* XFS_IN_MAXLEVELS */
struct xfs_perag *m_perag; /* per-ag accounting info */
struct rw_semaphore m_peraglock; /* lock for m_perag (pointer) */
sema_t m_growlock; /* growfs mutex */
struct mutex m_growlock; /* growfs mutex */
int m_fixedfsid[2]; /* unchanged for life of FS */
uint m_dmevmask; /* DMI events for this FS */
__uint64_t m_flags; /* global mount flags */
@ -415,8 +421,8 @@ typedef struct xfs_mount {
uint m_chsize; /* size of next field */
struct xfs_chash *m_chash; /* fs private inode per-cluster
* hash table */
struct xfs_dmops m_dm_ops; /* vector of DMI ops */
struct xfs_qmops m_qm_ops; /* vector of XQM ops */
struct xfs_dmops *m_dm_ops; /* vector of DMI ops */
struct xfs_qmops *m_qm_ops; /* vector of XQM ops */
struct xfs_ioops m_io_ops; /* vector of I/O ops */
atomic_t m_active_trans; /* number trans frozen */
#ifdef HAVE_PERCPU_SB
@ -426,6 +432,12 @@ typedef struct xfs_mount {
struct mutex m_icsb_mutex; /* balancer sync lock */
#endif
struct xfs_mru_cache *m_filestream; /* per-mount filestream data */
struct task_struct *m_sync_task; /* generalised sync thread */
bhv_vfs_sync_work_t m_sync_work; /* work item for VFS_SYNC */
struct list_head m_sync_list; /* sync thread work item list */
spinlock_t m_sync_lock; /* work item list lock */
int m_sync_seq; /* sync thread generation no. */
wait_queue_head_t m_wait_single_sync_task;
} xfs_mount_t;
/*
@ -435,7 +447,7 @@ typedef struct xfs_mount {
must be synchronous except
for space allocations */
#define XFS_MOUNT_INO64 (1ULL << 1)
/* (1ULL << 2) -- currently unused */
#define XFS_MOUNT_DMAPI (1ULL << 2) /* dmapi is enabled */
#define XFS_MOUNT_WAS_CLEAN (1ULL << 3)
#define XFS_MOUNT_FS_SHUTDOWN (1ULL << 4) /* atomic stop of all filesystem
operations, typically for
@ -445,7 +457,7 @@ typedef struct xfs_mount {
#define XFS_MOUNT_NOALIGN (1ULL << 7) /* turn off stripe alignment
allocations */
#define XFS_MOUNT_ATTR2 (1ULL << 8) /* allow use of attr2 format */
/* (1ULL << 9) -- currently unused */
#define XFS_MOUNT_GRPID (1ULL << 9) /* group-ID assigned from directory */
#define XFS_MOUNT_NORECOVERY (1ULL << 10) /* no recovery - dirty fs */
#define XFS_MOUNT_SHARED (1ULL << 11) /* shared mount */
#define XFS_MOUNT_DFLT_IOSIZE (1ULL << 12) /* set default i/o size */
@ -453,13 +465,13 @@ typedef struct xfs_mount {
/* osyncisdsync is now default*/
#define XFS_MOUNT_32BITINODES (1ULL << 14) /* do not create inodes above
* 32 bits in size */
/* (1ULL << 15) -- currently unused */
#define XFS_MOUNT_SMALL_INUMS (1ULL << 15) /* users wants 32bit inodes */
#define XFS_MOUNT_NOUUID (1ULL << 16) /* ignore uuid during mount */
#define XFS_MOUNT_BARRIER (1ULL << 17)
#define XFS_MOUNT_IDELETE (1ULL << 18) /* delete empty inode clusters*/
#define XFS_MOUNT_SWALLOC (1ULL << 19) /* turn on stripe width
* allocation */
#define XFS_MOUNT_IHASHSIZE (1ULL << 20) /* inode hash table size */
#define XFS_MOUNT_RDONLY (1ULL << 20) /* read-only fs */
#define XFS_MOUNT_DIRSYNC (1ULL << 21) /* synchronous directory ops */
#define XFS_MOUNT_COMPAT_IOSIZE (1ULL << 22) /* don't report large preferred
* I/O size in stat() */
@ -518,8 +530,10 @@ xfs_preferred_iosize(xfs_mount_t *mp)
#define XFS_LAST_UNMOUNT_WAS_CLEAN(mp) \
((mp)->m_flags & XFS_MOUNT_WAS_CLEAN)
#define XFS_FORCED_SHUTDOWN(mp) ((mp)->m_flags & XFS_MOUNT_FS_SHUTDOWN)
void xfs_do_force_shutdown(struct xfs_mount *mp, int flags, char *fname,
int lnnum);
#define xfs_force_shutdown(m,f) \
bhv_vfs_force_shutdown((XFS_MTOVFS(m)), f, __FILE__, __LINE__)
xfs_do_force_shutdown(m, f, __FILE__, __LINE__)
/*
* Flags for xfs_mountfs
@ -533,28 +547,6 @@ xfs_preferred_iosize(xfs_mount_t *mp)
/* XFS_MFSI_CONVERT_SUNIT */
#define XFS_MFSI_QUIET 0x40 /* Be silent if mount errors found */
/*
* Macros for getting from mount to vfs and back.
*/
#define XFS_MTOVFS(mp) xfs_mtovfs(mp)
static inline struct bhv_vfs *xfs_mtovfs(xfs_mount_t *mp)
{
return bhvtovfs(&mp->m_bhv);
}
#define XFS_BHVTOM(bdp) xfs_bhvtom(bdp)
static inline xfs_mount_t *xfs_bhvtom(bhv_desc_t *bdp)
{
return (xfs_mount_t *)BHV_PDATA(bdp);
}
#define XFS_VFSTOM(vfs) xfs_vfstom(vfs)
static inline xfs_mount_t *xfs_vfstom(bhv_vfs_t *vfs)
{
return XFS_BHVTOM(bhv_lookup_range(VFS_BHVHEAD(vfs),
VFS_POSITION_XFS, VFS_POSITION_XFS));
}
#define XFS_DADDR_TO_AGNO(mp,d) xfs_daddr_to_agno(mp,d)
static inline xfs_agnumber_t
xfs_daddr_to_agno(struct xfs_mount *mp, xfs_daddr_t d)
@ -572,6 +564,21 @@ xfs_daddr_to_agbno(struct xfs_mount *mp, xfs_daddr_t d)
return (xfs_agblock_t) do_div(ld, mp->m_sb.sb_agblocks);
}
/*
* perag get/put wrappers for eventual ref counting
*/
static inline xfs_perag_t *
xfs_get_perag(struct xfs_mount *mp, xfs_ino_t ino)
{
return &mp->m_perag[XFS_INO_TO_AGNO(mp, ino)];
}
static inline void
xfs_put_perag(struct xfs_mount *mp, xfs_perag_t *pag)
{
/* nothing to see here, move along */
}
/*
* Per-cpu superblock locking functions
*/
@ -609,8 +616,8 @@ typedef struct xfs_mod_sb {
extern xfs_mount_t *xfs_mount_init(void);
extern void xfs_mod_sb(xfs_trans_t *, __int64_t);
extern int xfs_log_sbcount(xfs_mount_t *, uint);
extern void xfs_mount_free(xfs_mount_t *mp, int remove_bhv);
extern int xfs_mountfs(struct bhv_vfs *, xfs_mount_t *mp, int);
extern void xfs_mount_free(xfs_mount_t *mp);
extern int xfs_mountfs(xfs_mount_t *mp, int);
extern void xfs_mountfs_check_barriers(xfs_mount_t *mp);
extern int xfs_unmountfs(xfs_mount_t *, struct cred *);
@ -626,16 +633,19 @@ extern struct xfs_buf *xfs_getsb(xfs_mount_t *, int);
extern int xfs_readsb(xfs_mount_t *, int);
extern void xfs_freesb(xfs_mount_t *);
extern int xfs_fs_writable(xfs_mount_t *);
extern void xfs_do_force_shutdown(bhv_desc_t *, int, char *, int);
extern int xfs_syncsub(xfs_mount_t *, int, int *);
extern int xfs_sync_inodes(xfs_mount_t *, int, int *);
extern xfs_agnumber_t xfs_initialize_perag(struct bhv_vfs *, xfs_mount_t *,
xfs_agnumber_t);
extern void xfs_xlatesb(void *, struct xfs_sb *, int, __int64_t);
extern xfs_agnumber_t xfs_initialize_perag(xfs_mount_t *, xfs_agnumber_t);
extern void xfs_sb_from_disk(struct xfs_sb *, struct xfs_dsb *);
extern void xfs_sb_to_disk(struct xfs_dsb *, struct xfs_sb *, __int64_t);
extern int xfs_sb_validate_fsb_count(struct xfs_sb *, __uint64_t);
extern struct xfs_dmops xfs_dmcore_stub;
extern struct xfs_qmops xfs_qmcore_stub;
extern int xfs_dmops_get(struct xfs_mount *, struct xfs_mount_args *);
extern void xfs_dmops_put(struct xfs_mount *);
extern int xfs_qmops_get(struct xfs_mount *, struct xfs_mount_args *);
extern void xfs_qmops_put(struct xfs_mount *);
extern struct xfs_dmops xfs_dmcore_xfs;
extern struct xfs_ioops xfs_iocore_xfs;
extern int xfs_init(void);

View file

@ -28,6 +28,8 @@
#include "xfs_mount.h"
#include "xfs_quota.h"
#include "xfs_error.h"
#include "xfs_clnt.h"
STATIC struct xfs_dquot *
xfs_dqvopchown_default(
@ -64,7 +66,7 @@ xfs_mount_reset_sbqflags(xfs_mount_t *mp)
* if the fs is readonly, let the incore superblock run
* with quotas off but don't flush the update out to disk
*/
if (XFS_MTOVFS(mp)->vfs_flag & VFS_RDONLY)
if (mp->m_flags & XFS_MOUNT_RDONLY)
return 0;
#ifdef QUOTADEBUG
xfs_fs_cmn_err(CE_NOTE, mp, "Writing superblock quota changes");
@ -110,7 +112,7 @@ xfs_noquota_init(
return error;
}
xfs_qmops_t xfs_qmcore_stub = {
static struct xfs_qmops xfs_qmcore_stub = {
.xfs_qminit = (xfs_qminit_t) xfs_noquota_init,
.xfs_qmdone = (xfs_qmdone_t) fs_noerr,
.xfs_qmmount = (xfs_qmmount_t) fs_noerr,
@ -124,4 +126,38 @@ xfs_qmops_t xfs_qmcore_stub = {
.xfs_dqvoprename = (xfs_dqvoprename_t) fs_noerr,
.xfs_dqvopchown = xfs_dqvopchown_default,
.xfs_dqvopchownresv = (xfs_dqvopchownresv_t) fs_noerr,
.xfs_dqstatvfs = (xfs_dqstatvfs_t) fs_noval,
.xfs_dqsync = (xfs_dqsync_t) fs_noerr,
.xfs_quotactl = (xfs_quotactl_t) fs_nosys,
};
int
xfs_qmops_get(struct xfs_mount *mp, struct xfs_mount_args *args)
{
if (args->flags & (XFSMNT_UQUOTA | XFSMNT_PQUOTA | XFSMNT_GQUOTA)) {
struct xfs_qmops *ops;
ops = symbol_get(xfs_qmcore_xfs);
if (!ops) {
request_module("xfs_quota");
ops = symbol_get(xfs_qmcore_xfs);
}
if (!ops) {
cmn_err(CE_WARN, "XFS: no quota support available.");
return EINVAL;
}
mp->m_qm_ops = ops;
} else {
mp->m_qm_ops = &xfs_qmcore_stub;
}
return 0;
}
void
xfs_qmops_put(struct xfs_mount *mp)
{
if (mp->m_qm_ops != &xfs_qmcore_stub)
symbol_put(xfs_qmcore_xfs);
}

View file

@ -330,12 +330,12 @@ typedef struct xfs_dqtrxops {
} xfs_dqtrxops_t;
#define XFS_DQTRXOP(mp, tp, op, args...) \
((mp)->m_qm_ops.xfs_dqtrxops ? \
((mp)->m_qm_ops.xfs_dqtrxops->op)(tp, ## args) : 0)
((mp)->m_qm_ops->xfs_dqtrxops ? \
((mp)->m_qm_ops->xfs_dqtrxops->op)(tp, ## args) : 0)
#define XFS_DQTRXOP_VOID(mp, tp, op, args...) \
((mp)->m_qm_ops.xfs_dqtrxops ? \
((mp)->m_qm_ops.xfs_dqtrxops->op)(tp, ## args) : (void)0)
((mp)->m_qm_ops->xfs_dqtrxops ? \
((mp)->m_qm_ops->xfs_dqtrxops->op)(tp, ## args) : (void)0)
#define XFS_TRANS_DUP_DQINFO(mp, otp, ntp) \
XFS_DQTRXOP_VOID(mp, otp, qo_dup_dqinfo, ntp)
@ -364,7 +364,7 @@ typedef struct xfs_dqtrxops {
extern int xfs_qm_dqcheck(xfs_disk_dquot_t *, xfs_dqid_t, uint, uint, char *);
extern int xfs_mount_reset_sbqflags(struct xfs_mount *);
extern struct bhv_module_vfsops xfs_qmops;
extern struct xfs_qmops xfs_qmcore_xfs;
#endif /* __KERNEL__ */

View file

@ -22,6 +22,7 @@
#include "xfs_inum.h"
#include "xfs_trans.h"
#include "xfs_sb.h"
#include "xfs_ag.h"
#include "xfs_dir2.h"
#include "xfs_dmapi.h"
#include "xfs_mount.h"
@ -128,8 +129,7 @@ xfs_lock_for_rename(
lock_mode = xfs_ilock_map_shared(dp2);
}
error = xfs_dir_lookup_int(XFS_ITOBHV(dp2), lock_mode,
vname2, &inum2, &ip2);
error = xfs_dir_lookup_int(dp2, lock_mode, vname2, &inum2, &ip2);
if (error == ENOENT) { /* target does not need to exist. */
inum2 = 0;
} else if (error) {
@ -221,15 +221,15 @@ xfs_lock_for_rename(
*/
int
xfs_rename(
bhv_desc_t *src_dir_bdp,
xfs_inode_t *src_dp,
bhv_vname_t *src_vname,
bhv_vnode_t *target_dir_vp,
bhv_vname_t *target_vname,
cred_t *credp)
bhv_vname_t *target_vname)
{
bhv_vnode_t *src_dir_vp = XFS_ITOV(src_dp);
xfs_trans_t *tp;
xfs_inode_t *src_dp, *target_dp, *src_ip, *target_ip;
xfs_mount_t *mp;
xfs_inode_t *target_dp, *src_ip, *target_ip;
xfs_mount_t *mp = src_dp->i_mount;
int new_parent; /* moving to a new dir */
int src_is_directory; /* src_name is a directory */
int error;
@ -239,7 +239,6 @@ xfs_rename(
int committed;
xfs_inode_t *inodes[4];
int target_ip_dropped = 0; /* dropped target_ip link? */
bhv_vnode_t *src_dir_vp;
int spaceres;
int target_link_zero = 0;
int num_inodes;
@ -248,9 +247,8 @@ xfs_rename(
int src_namelen = VNAMELEN(src_vname);
int target_namelen = VNAMELEN(target_vname);
src_dir_vp = BHV_TO_VNODE(src_dir_bdp);
vn_trace_entry(src_dir_vp, "xfs_rename", (inst_t *)__return_address);
vn_trace_entry(target_dir_vp, "xfs_rename", (inst_t *)__return_address);
vn_trace_entry(src_dp, "xfs_rename", (inst_t *)__return_address);
vn_trace_entry(xfs_vtoi(target_dir_vp), "xfs_rename", (inst_t *)__return_address);
/*
* Find the XFS behavior descriptor for the target directory
@ -261,12 +259,8 @@ xfs_rename(
return XFS_ERROR(EXDEV);
}
src_dp = XFS_BHVTOI(src_dir_bdp);
mp = src_dp->i_mount;
if (DM_EVENT_ENABLED(src_dir_vp->v_vfsp, src_dp, DM_EVENT_RENAME) ||
DM_EVENT_ENABLED(target_dir_vp->v_vfsp,
target_dp, DM_EVENT_RENAME)) {
if (DM_EVENT_ENABLED(src_dp, DM_EVENT_RENAME) ||
DM_EVENT_ENABLED(target_dp, DM_EVENT_RENAME)) {
error = XFS_SEND_NAMESP(mp, DM_EVENT_RENAME,
src_dir_vp, DM_RIGHT_NULL,
target_dir_vp, DM_RIGHT_NULL,
@ -592,20 +586,16 @@ xfs_rename(
/*
* Let interposed file systems know about removed links.
*/
if (target_ip_dropped) {
bhv_vop_link_removed(XFS_ITOV(target_ip), target_dir_vp,
target_link_zero);
if (target_ip_dropped)
IRELE(target_ip);
}
IRELE(src_ip);
/* Fall through to std_return with error = 0 or errno from
* xfs_trans_commit */
std_return:
if (DM_EVENT_ENABLED(src_dir_vp->v_vfsp, src_dp, DM_EVENT_POSTRENAME) ||
DM_EVENT_ENABLED(target_dir_vp->v_vfsp,
target_dp, DM_EVENT_POSTRENAME)) {
if (DM_EVENT_ENABLED(src_dp, DM_EVENT_POSTRENAME) ||
DM_EVENT_ENABLED(target_dp, DM_EVENT_POSTRENAME)) {
(void) XFS_SEND_NAMESP (mp, DM_EVENT_POSTRENAME,
src_dir_vp, DM_RIGHT_NULL,
target_dir_vp, DM_RIGHT_NULL,

View file

@ -178,18 +178,15 @@ xfs_write_sync_logforce(
* the shop, make sure that absolutely nothing persistent happens to
* this filesystem after this point.
*/
void
xfs_do_force_shutdown(
bhv_desc_t *bdp,
xfs_mount_t *mp,
int flags,
char *fname,
int lnnum)
{
int logerror;
xfs_mount_t *mp;
mp = XFS_BHVTOM(bdp);
logerror = flags & SHUTDOWN_LOG_IO_ERROR;
if (!(flags & SHUTDOWN_FORCE_UMOUNT)) {

View file

@ -22,32 +22,6 @@ struct xfs_buf;
struct xfs_inode;
struct xfs_mount;
/*
* Maximum count of bmaps used by read and write paths.
*/
#define XFS_MAX_RW_NBMAPS 4
/*
* Counts of readahead buffers to use based on physical memory size.
* None of these should be more than XFS_MAX_RW_NBMAPS.
*/
#define XFS_RW_NREADAHEAD_16MB 2
#define XFS_RW_NREADAHEAD_32MB 3
#define XFS_RW_NREADAHEAD_K32 4
#define XFS_RW_NREADAHEAD_K64 4
/*
* Maximum size of a buffer that we\'ll map. Making this
* too big will degrade performance due to the number of
* pages which need to be gathered. Making it too small
* will prevent us from doing large I/O\'s to hardware that
* needs it.
*
* This is currently set to 512 KB.
*/
#define XFS_MAX_BMAP_LEN_BB 1024
#define XFS_MAX_BMAP_LEN_BYTES 524288
/*
* Convert the given file system block to a disk block.
* We have to treat it differently based on whether the
@ -116,14 +90,6 @@ extern void xfs_ioerror_alert(char *func, struct xfs_mount *mp,
/*
* Prototypes for functions in xfs_vnodeops.c.
*/
extern int xfs_rwlock(bhv_desc_t *bdp, bhv_vrwlock_t write_lock);
extern void xfs_rwunlock(bhv_desc_t *bdp, bhv_vrwlock_t write_lock);
extern int xfs_setattr(bhv_desc_t *, bhv_vattr_t *vap, int flags,
cred_t *credp);
extern int xfs_change_file_space(bhv_desc_t *bdp, int cmd, xfs_flock64_t *bf,
xfs_off_t offset, cred_t *credp, int flags);
extern int xfs_set_dmattrs(bhv_desc_t *bdp, u_int evmask, u_int16_t state,
cred_t *credp);
extern int xfs_free_eofblocks(struct xfs_mount *mp, struct xfs_inode *ip,
int flags);

View file

@ -87,8 +87,10 @@ struct xfs_mount;
(XFS_SB_VERSION2_OKREALFBITS | \
XFS_SB_VERSION2_OKSASHFBITS )
typedef struct xfs_sb
{
/*
* Superblock - in core version. Must match the ondisk version below.
*/
typedef struct xfs_sb {
__uint32_t sb_magicnum; /* magic number == XFS_SB_MAGIC */
__uint32_t sb_blocksize; /* logical block size, bytes */
xfs_drfsbno_t sb_dblocks; /* number of data blocks */
@ -145,6 +147,66 @@ typedef struct xfs_sb
__uint32_t sb_features2; /* additional feature bits */
} xfs_sb_t;
/*
* Superblock - on disk version. Must match the in core version below.
*/
typedef struct xfs_dsb {
__be32 sb_magicnum; /* magic number == XFS_SB_MAGIC */
__be32 sb_blocksize; /* logical block size, bytes */
__be64 sb_dblocks; /* number of data blocks */
__be64 sb_rblocks; /* number of realtime blocks */
__be64 sb_rextents; /* number of realtime extents */
uuid_t sb_uuid; /* file system unique id */
__be64 sb_logstart; /* starting block of log if internal */
__be64 sb_rootino; /* root inode number */
__be64 sb_rbmino; /* bitmap inode for realtime extents */
__be64 sb_rsumino; /* summary inode for rt bitmap */
__be32 sb_rextsize; /* realtime extent size, blocks */
__be32 sb_agblocks; /* size of an allocation group */
__be32 sb_agcount; /* number of allocation groups */
__be32 sb_rbmblocks; /* number of rt bitmap blocks */
__be32 sb_logblocks; /* number of log blocks */
__be16 sb_versionnum; /* header version == XFS_SB_VERSION */
__be16 sb_sectsize; /* volume sector size, bytes */
__be16 sb_inodesize; /* inode size, bytes */
__be16 sb_inopblock; /* inodes per block */
char sb_fname[12]; /* file system name */
__u8 sb_blocklog; /* log2 of sb_blocksize */
__u8 sb_sectlog; /* log2 of sb_sectsize */
__u8 sb_inodelog; /* log2 of sb_inodesize */
__u8 sb_inopblog; /* log2 of sb_inopblock */
__u8 sb_agblklog; /* log2 of sb_agblocks (rounded up) */
__u8 sb_rextslog; /* log2 of sb_rextents */
__u8 sb_inprogress; /* mkfs is in progress, don't mount */
__u8 sb_imax_pct; /* max % of fs for inode space */
/* statistics */
/*
* These fields must remain contiguous. If you really
* want to change their layout, make sure you fix the
* code in xfs_trans_apply_sb_deltas().
*/
__be64 sb_icount; /* allocated inodes */
__be64 sb_ifree; /* free inodes */
__be64 sb_fdblocks; /* free data blocks */
__be64 sb_frextents; /* free realtime extents */
/*
* End contiguous fields.
*/
__be64 sb_uquotino; /* user quota inode */
__be64 sb_gquotino; /* group quota inode */
__be16 sb_qflags; /* quota flags */
__u8 sb_flags; /* misc. flags */
__u8 sb_shared_vn; /* shared version number */
__be32 sb_inoalignmt; /* inode chunk alignment, fsblocks */
__be32 sb_unit; /* stripe or raid unit */
__be32 sb_width; /* stripe or raid width */
__u8 sb_dirblklog; /* log2 of dir block size (fsbs) */
__u8 sb_logsectlog; /* log2 of the log sector size */
__be16 sb_logsectsize; /* sector size for the log, bytes */
__be32 sb_logsunit; /* stripe unit size for the log */
__be32 sb_features2; /* additional feature bits */
} xfs_dsb_t;
/*
* Sequence number values for the fields.
*/
@ -446,7 +508,7 @@ static inline void xfs_sb_version_addattr2(xfs_sb_t *sbp)
#define XFS_SB_DADDR ((xfs_daddr_t)0) /* daddr in filesystem/ag */
#define XFS_SB_BLOCK(mp) XFS_HDR_BLOCK(mp, XFS_SB_DADDR)
#define XFS_BUF_TO_SBP(bp) ((xfs_sb_t *)XFS_BUF_PTR(bp))
#define XFS_BUF_TO_SBP(bp) ((xfs_dsb_t *)XFS_BUF_PTR(bp))
#define XFS_HDR_BLOCK(mp,d) ((xfs_agblock_t)XFS_BB_TO_FSBT(mp,d))
#define XFS_DADDR_TO_FSB(mp,d) XFS_AGB_TO_FSB(mp, \

View file

@ -234,7 +234,7 @@ xfs_trans_alloc(
xfs_mount_t *mp,
uint type)
{
vfs_wait_for_freeze(XFS_MTOVFS(mp), SB_FREEZE_TRANS);
xfs_wait_for_freeze(mp, SB_FREEZE_TRANS);
return _xfs_trans_alloc(mp, type);
}
@ -548,7 +548,7 @@ STATIC void
xfs_trans_apply_sb_deltas(
xfs_trans_t *tp)
{
xfs_sb_t *sbp;
xfs_dsb_t *sbp;
xfs_buf_t *bp;
int whole = 0;
@ -566,57 +566,51 @@ xfs_trans_apply_sb_deltas(
* Only update the superblock counters if we are logging them
*/
if (!xfs_sb_version_haslazysbcount(&(tp->t_mountp->m_sb))) {
if (tp->t_icount_delta != 0) {
INT_MOD(sbp->sb_icount, ARCH_CONVERT, tp->t_icount_delta);
}
if (tp->t_ifree_delta != 0) {
INT_MOD(sbp->sb_ifree, ARCH_CONVERT, tp->t_ifree_delta);
}
if (tp->t_fdblocks_delta != 0) {
INT_MOD(sbp->sb_fdblocks, ARCH_CONVERT, tp->t_fdblocks_delta);
}
if (tp->t_res_fdblocks_delta != 0) {
INT_MOD(sbp->sb_fdblocks, ARCH_CONVERT, tp->t_res_fdblocks_delta);
}
if (tp->t_icount_delta)
be64_add(&sbp->sb_icount, tp->t_icount_delta);
if (tp->t_ifree_delta)
be64_add(&sbp->sb_ifree, tp->t_ifree_delta);
if (tp->t_fdblocks_delta)
be64_add(&sbp->sb_fdblocks, tp->t_fdblocks_delta);
if (tp->t_res_fdblocks_delta)
be64_add(&sbp->sb_fdblocks, tp->t_res_fdblocks_delta);
}
if (tp->t_frextents_delta != 0) {
INT_MOD(sbp->sb_frextents, ARCH_CONVERT, tp->t_frextents_delta);
}
if (tp->t_res_frextents_delta != 0) {
INT_MOD(sbp->sb_frextents, ARCH_CONVERT, tp->t_res_frextents_delta);
}
if (tp->t_dblocks_delta != 0) {
INT_MOD(sbp->sb_dblocks, ARCH_CONVERT, tp->t_dblocks_delta);
if (tp->t_frextents_delta)
be64_add(&sbp->sb_frextents, tp->t_frextents_delta);
if (tp->t_res_frextents_delta)
be64_add(&sbp->sb_frextents, tp->t_res_frextents_delta);
if (tp->t_dblocks_delta) {
be64_add(&sbp->sb_dblocks, tp->t_dblocks_delta);
whole = 1;
}
if (tp->t_agcount_delta != 0) {
INT_MOD(sbp->sb_agcount, ARCH_CONVERT, tp->t_agcount_delta);
if (tp->t_agcount_delta) {
be32_add(&sbp->sb_agcount, tp->t_agcount_delta);
whole = 1;
}
if (tp->t_imaxpct_delta != 0) {
INT_MOD(sbp->sb_imax_pct, ARCH_CONVERT, tp->t_imaxpct_delta);
if (tp->t_imaxpct_delta) {
sbp->sb_imax_pct += tp->t_imaxpct_delta;
whole = 1;
}
if (tp->t_rextsize_delta != 0) {
INT_MOD(sbp->sb_rextsize, ARCH_CONVERT, tp->t_rextsize_delta);
if (tp->t_rextsize_delta) {
be32_add(&sbp->sb_rextsize, tp->t_rextsize_delta);
whole = 1;
}
if (tp->t_rbmblocks_delta != 0) {
INT_MOD(sbp->sb_rbmblocks, ARCH_CONVERT, tp->t_rbmblocks_delta);
if (tp->t_rbmblocks_delta) {
be32_add(&sbp->sb_rbmblocks, tp->t_rbmblocks_delta);
whole = 1;
}
if (tp->t_rblocks_delta != 0) {
INT_MOD(sbp->sb_rblocks, ARCH_CONVERT, tp->t_rblocks_delta);
if (tp->t_rblocks_delta) {
be64_add(&sbp->sb_rblocks, tp->t_rblocks_delta);
whole = 1;
}
if (tp->t_rextents_delta != 0) {
INT_MOD(sbp->sb_rextents, ARCH_CONVERT, tp->t_rextents_delta);
if (tp->t_rextents_delta) {
be64_add(&sbp->sb_rextents, tp->t_rextents_delta);
whole = 1;
}
if (tp->t_rextslog_delta != 0) {
INT_MOD(sbp->sb_rextslog, ARCH_CONVERT, tp->t_rextslog_delta);
if (tp->t_rextslog_delta) {
sbp->sb_rextslog += tp->t_rextslog_delta;
whole = 1;
}
@ -624,17 +618,17 @@ xfs_trans_apply_sb_deltas(
/*
* Log the whole thing, the fields are noncontiguous.
*/
xfs_trans_log_buf(tp, bp, 0, sizeof(xfs_sb_t) - 1);
xfs_trans_log_buf(tp, bp, 0, sizeof(xfs_dsb_t) - 1);
else
/*
* Since all the modifiable fields are contiguous, we
* can get away with this.
*/
xfs_trans_log_buf(tp, bp, offsetof(xfs_sb_t, sb_icount),
offsetof(xfs_sb_t, sb_frextents) +
xfs_trans_log_buf(tp, bp, offsetof(xfs_dsb_t, sb_icount),
offsetof(xfs_dsb_t, sb_frextents) +
sizeof(sbp->sb_frextents) - 1);
XFS_MTOVFS(tp->t_mountp)->vfs_super->s_dirt = 1;
tp->t_mountp->m_super->s_dirt = 1;
}
/*

View file

@ -22,6 +22,7 @@
#include "xfs_inum.h"
#include "xfs_trans.h"
#include "xfs_sb.h"
#include "xfs_ag.h"
#include "xfs_dmapi.h"
#include "xfs_mount.h"
#include "xfs_trans_priv.h"

View file

@ -22,6 +22,7 @@
#include "xfs_inum.h"
#include "xfs_trans.h"
#include "xfs_sb.h"
#include "xfs_ag.h"
#include "xfs_dmapi.h"
#include "xfs_mount.h"
#include "xfs_trans_priv.h"

View file

@ -151,18 +151,6 @@ typedef __uint8_t xfs_arch_t; /* architecture of an xfs fs */
*/
#define MAXNAMELEN 256
typedef struct xfs_dirent { /* data from readdir() */
xfs_ino_t d_ino; /* inode number of entry */
xfs_off_t d_off; /* offset of disk directory entry */
unsigned short d_reclen; /* length of this record */
char d_name[1]; /* name of file */
} xfs_dirent_t;
#define DIRENTBASESIZE (((xfs_dirent_t *)0)->d_name - (char *)0)
#define DIRENTSIZE(namelen) \
((DIRENTBASESIZE + (namelen) + \
sizeof(xfs_off_t)) & ~(sizeof(xfs_off_t) - 1))
typedef enum {
XFS_LOOKUP_EQi, XFS_LOOKUP_LEi, XFS_LOOKUP_GEi
} xfs_lookup_t;

View file

@ -65,20 +65,15 @@ xfs_get_dir_entry(
int
xfs_dir_lookup_int(
bhv_desc_t *dir_bdp,
xfs_inode_t *dp,
uint lock_mode,
bhv_vname_t *dentry,
xfs_ino_t *inum,
xfs_inode_t **ipp)
{
bhv_vnode_t *dir_vp;
xfs_inode_t *dp;
int error;
dir_vp = BHV_TO_VNODE(dir_bdp);
vn_trace_entry(dir_vp, __FUNCTION__, (inst_t *)__return_address);
dp = XFS_BHVTOI(dir_bdp);
vn_trace_entry(dp, __FUNCTION__, (inst_t *)__return_address);
error = xfs_dir_lookup(NULL, dp, VNAME(dentry), VNAMELEN(dentry), inum);
if (!error) {

View file

@ -20,13 +20,11 @@
#define IRELE(ip) VN_RELE(XFS_ITOV(ip))
#define IHOLD(ip) VN_HOLD(XFS_ITOV(ip))
#define ITRACE(ip) vn_trace_ref(XFS_ITOV(ip), __FILE__, __LINE__, \
#define ITRACE(ip) vn_trace_ref(ip, __FILE__, __LINE__, \
(inst_t *)__return_address)
extern int xfs_rename (bhv_desc_t *, bhv_vname_t *, bhv_vnode_t *,
bhv_vname_t *, cred_t *);
extern int xfs_get_dir_entry (bhv_vname_t *, xfs_inode_t **);
extern int xfs_dir_lookup_int (bhv_desc_t *, uint, bhv_vname_t *, xfs_ino_t *,
extern int xfs_dir_lookup_int (xfs_inode_t *, uint, bhv_vname_t *, xfs_ino_t *,
xfs_inode_t **);
extern int xfs_truncate_file (xfs_mount_t *, xfs_inode_t *);
extern int xfs_dir_ialloc (xfs_trans_t **, xfs_inode_t *, mode_t, xfs_nlink_t,

View file

@ -54,8 +54,9 @@
#include "xfs_mru_cache.h"
#include "xfs_filestream.h"
#include "xfs_fsops.h"
#include "xfs_vnodeops.h"
#include "xfs_vfsops.h"
STATIC int xfs_sync(bhv_desc_t *, int, cred_t *);
int
xfs_init(void)
@ -117,8 +118,8 @@ xfs_init(void)
xfs_ili_zone =
kmem_zone_init_flags(sizeof(xfs_inode_log_item_t), "xfs_ili",
KM_ZONE_SPREAD, NULL);
xfs_chashlist_zone =
kmem_zone_init_flags(sizeof(xfs_chashlist_t), "xfs_chashlist",
xfs_icluster_zone =
kmem_zone_init_flags(sizeof(xfs_icluster_t), "xfs_icluster",
KM_ZONE_SPREAD, NULL);
/*
@ -163,7 +164,7 @@ xfs_cleanup(void)
extern kmem_zone_t *xfs_efd_zone;
extern kmem_zone_t *xfs_efi_zone;
extern kmem_zone_t *xfs_buf_item_zone;
extern kmem_zone_t *xfs_chashlist_zone;
extern kmem_zone_t *xfs_icluster_zone;
xfs_cleanup_procfs();
xfs_sysctl_unregister();
@ -199,7 +200,7 @@ xfs_cleanup(void)
kmem_zone_destroy(xfs_efi_zone);
kmem_zone_destroy(xfs_ifork_zone);
kmem_zone_destroy(xfs_ili_zone);
kmem_zone_destroy(xfs_chashlist_zone);
kmem_zone_destroy(xfs_icluster_zone);
}
/*
@ -210,7 +211,6 @@ xfs_cleanup(void)
*/
STATIC int
xfs_start_flags(
struct bhv_vfs *vfs,
struct xfs_mount_args *ap,
struct xfs_mount *mp)
{
@ -238,17 +238,14 @@ xfs_start_flags(
mp->m_logbufs = ap->logbufs;
if (ap->logbufsize != -1 &&
ap->logbufsize != 0 &&
ap->logbufsize != 16 * 1024 &&
ap->logbufsize != 32 * 1024 &&
ap->logbufsize != 64 * 1024 &&
ap->logbufsize != 128 * 1024 &&
ap->logbufsize != 256 * 1024) {
(ap->logbufsize < XLOG_MIN_RECORD_BSIZE ||
ap->logbufsize > XLOG_MAX_RECORD_BSIZE ||
!is_power_of_2(ap->logbufsize))) {
cmn_err(CE_WARN,
"XFS: invalid logbufsize: %d [not 16k,32k,64k,128k or 256k]",
ap->logbufsize);
return XFS_ERROR(EINVAL);
}
mp->m_ihsize = ap->ihashsize;
mp->m_logbsize = ap->logbufsize;
mp->m_fsname_len = strlen(ap->fsname) + 1;
mp->m_fsname = kmem_alloc(mp->m_fsname_len, KM_SLEEP);
@ -295,8 +292,6 @@ xfs_start_flags(
mp->m_readio_log = mp->m_writeio_log = ap->iosizelog;
}
if (ap->flags & XFSMNT_IHASHSIZE)
mp->m_flags |= XFS_MOUNT_IHASHSIZE;
if (ap->flags & XFSMNT_IDELETE)
mp->m_flags |= XFS_MOUNT_IDELETE;
if (ap->flags & XFSMNT_DIRSYNC)
@ -311,7 +306,7 @@ xfs_start_flags(
* no recovery flag requires a read-only mount
*/
if (ap->flags & XFSMNT_NORECOVERY) {
if (!(vfs->vfs_flag & VFS_RDONLY)) {
if (!(mp->m_flags & XFS_MOUNT_RDONLY)) {
cmn_err(CE_WARN,
"XFS: tried to mount a FS read-write without recovery!");
return XFS_ERROR(EINVAL);
@ -329,6 +324,8 @@ xfs_start_flags(
if (ap->flags2 & XFSMNT2_FILESTREAMS)
mp->m_flags |= XFS_MOUNT_FILESTREAMS;
if (ap->flags & XFSMNT_DMAPI)
mp->m_flags |= XFS_MOUNT_DMAPI;
return 0;
}
@ -338,11 +335,10 @@ xfs_start_flags(
*/
STATIC int
xfs_finish_flags(
struct bhv_vfs *vfs,
struct xfs_mount_args *ap,
struct xfs_mount *mp)
{
int ronly = (vfs->vfs_flag & VFS_RDONLY);
int ronly = (mp->m_flags & XFS_MOUNT_RDONLY);
/* Fail a mount where the logbuf is smaller then the log stripe */
if (XFS_SB_VERSION_HASLOGV2(&mp->m_sb)) {
@ -403,6 +399,22 @@ xfs_finish_flags(
return XFS_ERROR(EINVAL);
}
if (ap->flags & XFSMNT_UQUOTA) {
mp->m_qflags |= (XFS_UQUOTA_ACCT | XFS_UQUOTA_ACTIVE);
if (ap->flags & XFSMNT_UQUOTAENF)
mp->m_qflags |= XFS_UQUOTA_ENFD;
}
if (ap->flags & XFSMNT_GQUOTA) {
mp->m_qflags |= (XFS_GQUOTA_ACCT | XFS_GQUOTA_ACTIVE);
if (ap->flags & XFSMNT_GQUOTAENF)
mp->m_qflags |= XFS_OQUOTA_ENFD;
} else if (ap->flags & XFSMNT_PQUOTA) {
mp->m_qflags |= (XFS_PQUOTA_ACCT | XFS_PQUOTA_ACTIVE);
if (ap->flags & XFSMNT_PQUOTAENF)
mp->m_qflags |= XFS_OQUOTA_ENFD;
}
return 0;
}
@ -418,30 +430,26 @@ xfs_finish_flags(
* they are present. The data subvolume has already been opened by
* get_sb_bdev() and is stored in vfsp->vfs_super->s_bdev.
*/
STATIC int
int
xfs_mount(
struct bhv_desc *bhvp,
struct xfs_mount *mp,
struct xfs_mount_args *args,
cred_t *credp)
{
struct bhv_vfs *vfsp = bhvtovfs(bhvp);
struct bhv_desc *p;
struct xfs_mount *mp = XFS_BHVTOM(bhvp);
struct block_device *ddev, *logdev, *rtdev;
int flags = 0, error;
ddev = vfsp->vfs_super->s_bdev;
ddev = mp->m_super->s_bdev;
logdev = rtdev = NULL;
/*
* Setup xfs_mount function vectors from available behaviors
*/
p = vfs_bhv_lookup(vfsp, VFS_POSITION_DM);
mp->m_dm_ops = p ? *(xfs_dmops_t *) vfs_bhv_custom(p) : xfs_dmcore_stub;
p = vfs_bhv_lookup(vfsp, VFS_POSITION_QM);
mp->m_qm_ops = p ? *(xfs_qmops_t *) vfs_bhv_custom(p) : xfs_qmcore_stub;
p = vfs_bhv_lookup(vfsp, VFS_POSITION_IO);
mp->m_io_ops = p ? *(xfs_ioops_t *) vfs_bhv_custom(p) : xfs_iocore_xfs;
error = xfs_dmops_get(mp, args);
if (error)
return error;
error = xfs_qmops_get(mp, args);
if (error)
return error;
mp->m_io_ops = xfs_iocore_xfs;
if (args->flags & XFSMNT_QUIET)
flags |= XFS_MFSI_QUIET;
@ -482,24 +490,30 @@ xfs_mount(
}
if (rtdev) {
mp->m_rtdev_targp = xfs_alloc_buftarg(rtdev, 1);
if (!mp->m_rtdev_targp)
if (!mp->m_rtdev_targp) {
xfs_blkdev_put(logdev);
xfs_blkdev_put(rtdev);
goto error0;
}
}
mp->m_logdev_targp = (logdev && logdev != ddev) ?
xfs_alloc_buftarg(logdev, 1) : mp->m_ddev_targp;
if (!mp->m_logdev_targp)
if (!mp->m_logdev_targp) {
xfs_blkdev_put(logdev);
xfs_blkdev_put(rtdev);
goto error0;
}
/*
* Setup flags based on mount(2) options and then the superblock
*/
error = xfs_start_flags(vfsp, args, mp);
error = xfs_start_flags(args, mp);
if (error)
goto error1;
error = xfs_readsb(mp, flags);
if (error)
goto error1;
error = xfs_finish_flags(vfsp, args, mp);
error = xfs_finish_flags(args, mp);
if (error)
goto error2;
@ -530,10 +544,12 @@ xfs_mount(
if ((error = xfs_filestream_mount(mp)))
goto error2;
error = XFS_IOINIT(vfsp, args, flags);
error = XFS_IOINIT(mp, args, flags);
if (error)
goto error2;
XFS_SEND_MOUNT(mp, DM_RIGHT_NULL, args->mtpt, args->fsname);
return 0;
error2:
@ -547,17 +563,17 @@ error1:
xfs_binval(mp->m_rtdev_targp);
error0:
xfs_unmountfs_close(mp, credp);
xfs_qmops_put(mp);
xfs_dmops_put(mp);
return error;
}
STATIC int
int
xfs_unmount(
bhv_desc_t *bdp,
xfs_mount_t *mp,
int flags,
cred_t *credp)
{
bhv_vfs_t *vfsp = bhvtovfs(bdp);
xfs_mount_t *mp = XFS_BHVTOM(bdp);
xfs_inode_t *rip;
bhv_vnode_t *rvp;
int unmount_event_wanted = 0;
@ -568,8 +584,9 @@ xfs_unmount(
rip = mp->m_rootip;
rvp = XFS_ITOV(rip);
if (vfsp->vfs_flag & VFS_DMI) {
error = XFS_SEND_PREUNMOUNT(mp, vfsp,
#ifdef HAVE_DMAPI
if (mp->m_flags & XFS_MOUNT_DMAPI) {
error = XFS_SEND_PREUNMOUNT(mp,
rvp, DM_RIGHT_NULL, rvp, DM_RIGHT_NULL,
NULL, NULL, 0, 0,
(mp->m_dmevmask & (1<<DM_EVENT_PREUNMOUNT))?
@ -580,7 +597,7 @@ xfs_unmount(
unmount_event_flags = (mp->m_dmevmask & (1<<DM_EVENT_UNMOUNT))?
0 : DM_FLAGS_UNWANTED;
}
#endif
/*
* First blow any referenced inode from this file system
* out of the reference cache, and delete the timer.
@ -612,8 +629,7 @@ xfs_unmount(
* referenced vnodes as well.
*/
if (XFS_FORCED_SHUTDOWN(mp)) {
error = xfs_sync(&mp->m_bhv,
(SYNC_WAIT | SYNC_CLOSE), credp);
error = xfs_sync(mp, SYNC_WAIT | SYNC_CLOSE);
ASSERT(error != EFSCORRUPTED);
}
xfs_unmountfs_needed = 1;
@ -627,7 +643,7 @@ out:
/* Note: mp structure must still exist for
* XFS_SEND_UNMOUNT() call.
*/
XFS_SEND_UNMOUNT(mp, vfsp, error == 0 ? rvp : NULL,
XFS_SEND_UNMOUNT(mp, error == 0 ? rvp : NULL,
DM_RIGHT_NULL, 0, error, unmount_event_flags);
}
if (xfs_unmountfs_needed) {
@ -636,6 +652,9 @@ out:
* and free the super block buffer & mount structures.
*/
xfs_unmountfs(mp, credp);
xfs_qmops_put(mp);
xfs_dmops_put(mp);
kmem_free(mp, sizeof(xfs_mount_t));
}
return XFS_ERROR(error);
@ -694,29 +713,26 @@ xfs_attr_quiesce(
xfs_unmountfs_writesb(mp);
}
STATIC int
int
xfs_mntupdate(
bhv_desc_t *bdp,
struct xfs_mount *mp,
int *flags,
struct xfs_mount_args *args)
{
bhv_vfs_t *vfsp = bhvtovfs(bdp);
xfs_mount_t *mp = XFS_BHVTOM(bdp);
if (!(*flags & MS_RDONLY)) { /* rw/ro -> rw */
if (vfsp->vfs_flag & VFS_RDONLY)
vfsp->vfs_flag &= ~VFS_RDONLY;
if (mp->m_flags & XFS_MOUNT_RDONLY)
mp->m_flags &= ~XFS_MOUNT_RDONLY;
if (args->flags & XFSMNT_BARRIER) {
mp->m_flags |= XFS_MOUNT_BARRIER;
xfs_mountfs_check_barriers(mp);
} else {
mp->m_flags &= ~XFS_MOUNT_BARRIER;
}
} else if (!(vfsp->vfs_flag & VFS_RDONLY)) { /* rw -> ro */
} else if (!(mp->m_flags & XFS_MOUNT_RDONLY)) { /* rw -> ro */
xfs_filestream_flush(mp);
bhv_vfs_sync(vfsp, SYNC_DATA_QUIESCE, NULL);
xfs_sync(mp, SYNC_DATA_QUIESCE);
xfs_attr_quiesce(mp);
vfsp->vfs_flag |= VFS_RDONLY;
mp->m_flags |= XFS_MOUNT_RDONLY;
}
return 0;
}
@ -811,14 +827,14 @@ fscorrupt_out2:
* vpp -- address of the caller's vnode pointer which should be
* set to the desired fs root vnode
*/
STATIC int
int
xfs_root(
bhv_desc_t *bdp,
xfs_mount_t *mp,
bhv_vnode_t **vpp)
{
bhv_vnode_t *vp;
vp = XFS_ITOV((XFS_BHVTOM(bdp))->m_rootip);
vp = XFS_ITOV(mp->m_rootip);
VN_HOLD(vp);
*vpp = vp;
return 0;
@ -831,19 +847,17 @@ xfs_root(
* the superblock lock in the mount structure to ensure a consistent
* snapshot of the counters returned.
*/
STATIC int
int
xfs_statvfs(
bhv_desc_t *bdp,
xfs_mount_t *mp,
bhv_statvfs_t *statp,
bhv_vnode_t *vp)
{
__uint64_t fakeinos;
xfs_extlen_t lsize;
xfs_mount_t *mp;
xfs_sb_t *sbp;
unsigned long s;
mp = XFS_BHVTOM(bdp);
sbp = &(mp->m_sb);
statp->f_type = XFS_SB_MAGIC;
@ -874,6 +888,8 @@ xfs_statvfs(
xfs_statvfs_fsid(statp, mp);
statp->f_namelen = MAXNAMELEN - 1;
if (vp)
XFS_QM_DQSTATVFS(xfs_vtoi(vp), statp);
return 0;
}
@ -920,14 +936,30 @@ xfs_statvfs(
* filesystem.
*
*/
/*ARGSUSED*/
STATIC int
int
xfs_sync(
bhv_desc_t *bdp,
int flags,
cred_t *credp)
xfs_mount_t *mp,
int flags)
{
xfs_mount_t *mp = XFS_BHVTOM(bdp);
int error;
/*
* Get the Quota Manager to flush the dquots.
*
* If XFS quota support is not enabled or this filesystem
* instance does not use quotas XFS_QM_DQSYNC will always
* return zero.
*/
error = XFS_QM_DQSYNC(mp, flags);
if (error) {
/*
* 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 (flags & SYNC_IOWAIT)
xfs_filestream_flush(mp);
@ -1015,7 +1047,7 @@ xfs_sync_inodes(
if (bypassed)
*bypassed = 0;
if (XFS_MTOVFS(mp)->vfs_flag & VFS_RDONLY)
if (mp->m_flags & XFS_MOUNT_RDONLY)
return 0;
error = 0;
last_error = 0;
@ -1189,12 +1221,13 @@ xfs_sync_inodes(
if (flags & SYNC_CLOSE) {
/* Shutdown case. Flush and invalidate. */
if (XFS_FORCED_SHUTDOWN(mp))
bhv_vop_toss_pages(vp, 0, -1, FI_REMAPF);
xfs_tosspages(ip, 0, -1,
FI_REMAPF);
else
error = bhv_vop_flushinval_pages(vp, 0,
-1, FI_REMAPF);
error = xfs_flushinval_pages(ip,
0, -1, FI_REMAPF);
} else if ((flags & SYNC_DELWRI) && VN_DIRTY(vp)) {
error = bhv_vop_flush_pages(vp, (xfs_off_t)0,
error = xfs_flush_pages(ip, 0,
-1, fflag, FI_NONE);
}
@ -1204,7 +1237,7 @@ xfs_sync_inodes(
* place after this point
*/
if (flags & SYNC_IOWAIT)
vn_iowait(vp);
vn_iowait(ip);
xfs_ilock(ip, XFS_ILOCK_SHARED);
}
@ -1598,13 +1631,12 @@ xfs_syncsub(
/*
* xfs_vget - called by DMAPI and NFSD to get vnode from file handle
*/
STATIC int
int
xfs_vget(
bhv_desc_t *bdp,
xfs_mount_t *mp,
bhv_vnode_t **vpp,
fid_t *fidp)
{
xfs_mount_t *mp = XFS_BHVTOM(bdp);
xfs_fid_t *xfid = (struct xfs_fid *)fidp;
xfs_inode_t *ip;
int error;
@ -1668,7 +1700,6 @@ xfs_vget(
#define MNTOPT_BSDGROUPS "bsdgroups" /* group-ID from parent directory */
#define MNTOPT_SYSVGROUPS "sysvgroups" /* group-ID from current process */
#define MNTOPT_ALLOCSIZE "allocsize" /* preferred allocation size */
#define MNTOPT_IHASHSIZE "ihashsize" /* size of inode hash table */
#define MNTOPT_NORECOVERY "norecovery" /* don't run XFS recovery */
#define MNTOPT_BARRIER "barrier" /* use writer barriers for log write and
* unwritten extent conversion */
@ -1683,6 +1714,21 @@ xfs_vget(
#define MNTOPT_ATTR2 "attr2" /* do use attr2 attribute format */
#define MNTOPT_NOATTR2 "noattr2" /* do not use attr2 attribute format */
#define MNTOPT_FILESTREAM "filestreams" /* use filestreams allocator */
#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 */
#define MNTOPT_DMAPI "dmapi" /* DMI enabled (DMAPI / XDSM) */
#define MNTOPT_XDSM "xdsm" /* DMI enabled (DMAPI / XDSM) */
#define MNTOPT_DMI "dmi" /* DMI enabled (DMAPI / XDSM) */
STATIC unsigned long
suffix_strtoul(char *s, char **endp, unsigned int base)
@ -1707,19 +1753,18 @@ suffix_strtoul(char *s, char **endp, unsigned int base)
return simple_strtoul((const char *)s, endp, base) << shift_left_factor;
}
STATIC int
int
xfs_parseargs(
struct bhv_desc *bhv,
struct xfs_mount *mp,
char *options,
struct xfs_mount_args *args,
int update)
{
bhv_vfs_t *vfsp = bhvtovfs(bhv);
char *this_char, *value, *eov;
int dsunit, dswidth, vol_dsunit, vol_dswidth;
int iosize;
int ikeep = 0;
args->flags |= XFSMNT_IDELETE;
args->flags |= XFSMNT_BARRIER;
args->flags2 |= XFSMNT2_COMPAT_IOSIZE;
@ -1794,21 +1839,12 @@ xfs_parseargs(
iosize = suffix_strtoul(value, &eov, 10);
args->flags |= XFSMNT_IOSIZE;
args->iosizelog = ffs(iosize) - 1;
} else if (!strcmp(this_char, MNTOPT_IHASHSIZE)) {
if (!value || !*value) {
cmn_err(CE_WARN,
"XFS: %s option requires an argument",
this_char);
return EINVAL;
}
args->flags |= XFSMNT_IHASHSIZE;
args->ihashsize = simple_strtoul(value, &eov, 10);
} else if (!strcmp(this_char, MNTOPT_GRPID) ||
!strcmp(this_char, MNTOPT_BSDGROUPS)) {
vfsp->vfs_flag |= VFS_GRPID;
mp->m_flags |= XFS_MOUNT_GRPID;
} else if (!strcmp(this_char, MNTOPT_NOGRPID) ||
!strcmp(this_char, MNTOPT_SYSVGROUPS)) {
vfsp->vfs_flag &= ~VFS_GRPID;
mp->m_flags &= ~XFS_MOUNT_GRPID;
} else if (!strcmp(this_char, MNTOPT_WSYNC)) {
args->flags |= XFSMNT_WSYNC;
} else if (!strcmp(this_char, MNTOPT_OSYNCISOSYNC)) {
@ -1858,6 +1894,7 @@ xfs_parseargs(
} else if (!strcmp(this_char, MNTOPT_NOBARRIER)) {
args->flags &= ~XFSMNT_BARRIER;
} else if (!strcmp(this_char, MNTOPT_IKEEP)) {
ikeep = 1;
args->flags &= ~XFSMNT_IDELETE;
} else if (!strcmp(this_char, MNTOPT_NOIKEEP)) {
args->flags |= XFSMNT_IDELETE;
@ -1871,6 +1908,38 @@ xfs_parseargs(
args->flags &= ~XFSMNT_ATTR2;
} else if (!strcmp(this_char, MNTOPT_FILESTREAM)) {
args->flags2 |= XFSMNT2_FILESTREAMS;
} else if (!strcmp(this_char, MNTOPT_NOQUOTA)) {
args->flags &= ~(XFSMNT_UQUOTAENF|XFSMNT_UQUOTA);
args->flags &= ~(XFSMNT_GQUOTAENF|XFSMNT_GQUOTA);
} else if (!strcmp(this_char, MNTOPT_QUOTA) ||
!strcmp(this_char, MNTOPT_UQUOTA) ||
!strcmp(this_char, MNTOPT_USRQUOTA)) {
args->flags |= XFSMNT_UQUOTA | XFSMNT_UQUOTAENF;
} else if (!strcmp(this_char, MNTOPT_QUOTANOENF) ||
!strcmp(this_char, MNTOPT_UQUOTANOENF)) {
args->flags |= XFSMNT_UQUOTA;
args->flags &= ~XFSMNT_UQUOTAENF;
} else if (!strcmp(this_char, MNTOPT_PQUOTA) ||
!strcmp(this_char, MNTOPT_PRJQUOTA)) {
args->flags |= XFSMNT_PQUOTA | XFSMNT_PQUOTAENF;
} else if (!strcmp(this_char, MNTOPT_PQUOTANOENF)) {
args->flags |= XFSMNT_PQUOTA;
args->flags &= ~XFSMNT_PQUOTAENF;
} else if (!strcmp(this_char, MNTOPT_GQUOTA) ||
!strcmp(this_char, MNTOPT_GRPQUOTA)) {
args->flags |= XFSMNT_GQUOTA | XFSMNT_GQUOTAENF;
} else if (!strcmp(this_char, MNTOPT_GQUOTANOENF)) {
args->flags |= XFSMNT_GQUOTA;
args->flags &= ~XFSMNT_GQUOTAENF;
} else if (!strcmp(this_char, MNTOPT_DMAPI)) {
args->flags |= XFSMNT_DMAPI;
} else if (!strcmp(this_char, MNTOPT_XDSM)) {
args->flags |= XFSMNT_DMAPI;
} else if (!strcmp(this_char, MNTOPT_DMI)) {
args->flags |= XFSMNT_DMAPI;
} else if (!strcmp(this_char, "ihashsize")) {
cmn_err(CE_WARN,
"XFS: ihashsize no longer used, option is deprecated.");
} else if (!strcmp(this_char, "osyncisdsync")) {
/* no-op, this is now the default */
cmn_err(CE_WARN,
@ -1886,7 +1955,7 @@ xfs_parseargs(
}
if (args->flags & XFSMNT_NORECOVERY) {
if ((vfsp->vfs_flag & VFS_RDONLY) == 0) {
if ((mp->m_flags & XFS_MOUNT_RDONLY) == 0) {
cmn_err(CE_WARN,
"XFS: no-recovery mounts must be read-only.");
return EINVAL;
@ -1899,6 +1968,18 @@ xfs_parseargs(
return EINVAL;
}
if ((args->flags & XFSMNT_GQUOTA) && (args->flags & XFSMNT_PQUOTA)) {
cmn_err(CE_WARN,
"XFS: cannot mount with both project and group quota");
return EINVAL;
}
if ((args->flags & XFSMNT_DMAPI) && *args->mtpt == '\0') {
printk("XFS: %s option needs the mount point option as well\n",
MNTOPT_DMAPI);
return EINVAL;
}
if ((dsunit && !dswidth) || (!dsunit && dswidth)) {
cmn_err(CE_WARN,
"XFS: sunit and swidth must be specified together");
@ -1912,6 +1993,18 @@ xfs_parseargs(
return EINVAL;
}
/*
* Applications using DMI filesystems often expect the
* inode generation number to be monotonically increasing.
* If we delete inode chunks we break this assumption, so
* keep unused inode chunks on disk for DMI filesystems
* until we come up with a better solution.
* Note that if "ikeep" or "noikeep" mount options are
* supplied, then they are honored.
*/
if (!(args->flags & XFSMNT_DMAPI) && !ikeep)
args->flags |= XFSMNT_IDELETE;
if ((args->flags & XFSMNT_NOALIGN) != XFSMNT_NOALIGN) {
if (dsunit) {
args->sunit = dsunit;
@ -1927,15 +2020,15 @@ xfs_parseargs(
done:
if (args->flags & XFSMNT_32BITINODES)
vfsp->vfs_flag |= VFS_32BITINODES;
mp->m_flags |= XFS_MOUNT_SMALL_INUMS;
if (args->flags2)
args->flags |= XFSMNT_FLAGS2;
return 0;
}
STATIC int
int
xfs_showargs(
struct bhv_desc *bhv,
struct xfs_mount *mp,
struct seq_file *m)
{
static struct proc_xfs_info {
@ -1953,17 +2046,12 @@ xfs_showargs(
{ 0, NULL }
};
struct proc_xfs_info *xfs_infop;
struct xfs_mount *mp = XFS_BHVTOM(bhv);
struct bhv_vfs *vfsp = XFS_MTOVFS(mp);
for (xfs_infop = xfs_info; xfs_infop->flag; xfs_infop++) {
if (mp->m_flags & xfs_infop->flag)
seq_puts(m, xfs_infop->str);
}
if (mp->m_flags & XFS_MOUNT_IHASHSIZE)
seq_printf(m, "," MNTOPT_IHASHSIZE "=%d", (int)mp->m_ihsize);
if (mp->m_flags & XFS_MOUNT_DFLT_IOSIZE)
seq_printf(m, "," MNTOPT_ALLOCSIZE "=%dk",
(int)(1 << mp->m_writeio_log) >> 10);
@ -1990,11 +2078,37 @@ xfs_showargs(
if (!(mp->m_flags & XFS_MOUNT_COMPAT_IOSIZE))
seq_printf(m, "," MNTOPT_LARGEIO);
if (!(vfsp->vfs_flag & VFS_32BITINODES))
if (!(mp->m_flags & XFS_MOUNT_SMALL_INUMS))
seq_printf(m, "," MNTOPT_64BITINODE);
if (vfsp->vfs_flag & VFS_GRPID)
if (mp->m_flags & XFS_MOUNT_GRPID)
seq_printf(m, "," MNTOPT_GRPID);
if (mp->m_qflags & XFS_UQUOTA_ACCT) {
if (mp->m_qflags & XFS_UQUOTA_ENFD)
seq_puts(m, "," MNTOPT_USRQUOTA);
else
seq_puts(m, "," MNTOPT_UQUOTANOENF);
}
if (mp->m_qflags & XFS_PQUOTA_ACCT) {
if (mp->m_qflags & XFS_OQUOTA_ENFD)
seq_puts(m, "," MNTOPT_PRJQUOTA);
else
seq_puts(m, "," MNTOPT_PQUOTANOENF);
}
if (mp->m_qflags & XFS_GQUOTA_ACCT) {
if (mp->m_qflags & XFS_OQUOTA_ENFD)
seq_puts(m, "," MNTOPT_GRPQUOTA);
else
seq_puts(m, "," MNTOPT_GQUOTANOENF);
}
if (!(mp->m_qflags & XFS_ALL_QUOTA_ACCT))
seq_puts(m, "," MNTOPT_NOQUOTA);
if (mp->m_flags & XFS_MOUNT_DMAPI)
seq_puts(m, "," MNTOPT_DMAPI);
return 0;
}
@ -2003,31 +2117,10 @@ xfs_showargs(
* need to take care of themetadata. Once that's done write a dummy
* record to dirty the log in case of a crash while frozen.
*/
STATIC void
void
xfs_freeze(
bhv_desc_t *bdp)
xfs_mount_t *mp)
{
xfs_mount_t *mp = XFS_BHVTOM(bdp);
xfs_attr_quiesce(mp);
xfs_fs_log_dummy(mp);
}
bhv_vfsops_t xfs_vfsops = {
BHV_IDENTITY_INIT(VFS_BHV_XFS,VFS_POSITION_XFS),
.vfs_parseargs = xfs_parseargs,
.vfs_showargs = xfs_showargs,
.vfs_mount = xfs_mount,
.vfs_unmount = xfs_unmount,
.vfs_mntupdate = xfs_mntupdate,
.vfs_root = xfs_root,
.vfs_statvfs = xfs_statvfs,
.vfs_sync = xfs_sync,
.vfs_vget = xfs_vget,
.vfs_dmapiops = (vfs_dmapiops_t)fs_nosys,
.vfs_quotactl = (vfs_quotactl_t)fs_nosys,
.vfs_init_vnode = xfs_initialize_vnode,
.vfs_force_shutdown = xfs_do_force_shutdown,
.vfs_freeze = xfs_freeze,
};

28
fs/xfs/xfs_vfsops.h Normal file
View file

@ -0,0 +1,28 @@
#ifndef _XFS_VFSOPS_H
#define _XFS_VFSOPS_H 1
struct cred;
struct fid;
struct inode;
struct kstatfs;
struct xfs_mount;
struct xfs_mount_args;
int xfs_mount(struct xfs_mount *mp, struct xfs_mount_args *args,
struct cred *credp);
int xfs_unmount(struct xfs_mount *mp, int flags, struct cred *credp);
int xfs_mntupdate(struct xfs_mount *mp, int *flags,
struct xfs_mount_args *args);
int xfs_root(struct xfs_mount *mp, bhv_vnode_t **vpp);
int xfs_statvfs(struct xfs_mount *mp, struct kstatfs *statp,
bhv_vnode_t *vp);
int xfs_sync(struct xfs_mount *mp, int flags);
int xfs_vget(struct xfs_mount *mp, bhv_vnode_t **vpp, struct fid *fidp);
int xfs_parseargs(struct xfs_mount *mp, char *options,
struct xfs_mount_args *args, int update);
int xfs_showargs(struct xfs_mount *mp, struct seq_file *m);
void xfs_freeze(struct xfs_mount *mp);
void xfs_do_force_shutdown(struct xfs_mount *mp, int flags, char *fname,
int lnnum);
#endif /* _XFS_VFSOPS_H */

File diff suppressed because it is too large Load diff

86
fs/xfs/xfs_vnodeops.h Normal file
View file

@ -0,0 +1,86 @@
#ifndef _XFS_VNODEOPS_H
#define _XFS_VNODEOPS_H 1
struct attrlist_cursor_kern;
struct bhv_vattr;
struct cred;
struct file;
struct inode;
struct iovec;
struct kiocb;
struct pipe_inode_info;
struct uio;
struct xfs_inode;
struct xfs_iomap;
int xfs_open(struct xfs_inode *ip);
int xfs_getattr(struct xfs_inode *ip, struct bhv_vattr *vap, int flags);
int xfs_setattr(struct xfs_inode *ip, struct bhv_vattr *vap, int flags,
struct cred *credp);
int xfs_access(struct xfs_inode *ip, int mode, struct cred *credp);
int xfs_readlink(struct xfs_inode *ip, char *link);
int xfs_fsync(struct xfs_inode *ip, int flag, xfs_off_t start,
xfs_off_t stop);
int xfs_release(struct xfs_inode *ip);
int xfs_inactive(struct xfs_inode *ip);
int xfs_lookup(struct xfs_inode *dp, bhv_vname_t *dentry,
bhv_vnode_t **vpp);
int xfs_create(struct xfs_inode *dp, bhv_vname_t *dentry, mode_t mode,
xfs_dev_t rdev, bhv_vnode_t **vpp, struct cred *credp);
int xfs_remove(struct xfs_inode *dp, bhv_vname_t *dentry);
int xfs_link(struct xfs_inode *tdp, bhv_vnode_t *src_vp,
bhv_vname_t *dentry);
int xfs_mkdir(struct xfs_inode *dp, bhv_vname_t *dentry,
mode_t mode, bhv_vnode_t **vpp, struct cred *credp);
int xfs_rmdir(struct xfs_inode *dp, bhv_vname_t *dentry);
int xfs_readdir(struct xfs_inode *dp, void *dirent, size_t bufsize,
xfs_off_t *offset, filldir_t filldir);
int xfs_symlink(struct xfs_inode *dp, bhv_vname_t *dentry,
char *target_path, mode_t mode, bhv_vnode_t **vpp,
struct cred *credp);
int xfs_fid2(struct xfs_inode *ip, fid_t *fidp);
int xfs_rwlock(struct xfs_inode *ip, bhv_vrwlock_t locktype);
void xfs_rwunlock(struct xfs_inode *ip, bhv_vrwlock_t locktype);
int xfs_inode_flush(struct xfs_inode *ip, int flags);
int xfs_set_dmattrs(struct xfs_inode *ip, u_int evmask, u_int16_t state);
int xfs_reclaim(struct xfs_inode *ip);
int xfs_change_file_space(struct xfs_inode *ip, int cmd,
xfs_flock64_t *bf, xfs_off_t offset,
struct cred *credp, int attr_flags);
int xfs_rename(struct xfs_inode *src_dp, bhv_vname_t *src_vname,
bhv_vnode_t *target_dir_vp, bhv_vname_t *target_vname);
int xfs_attr_get(struct xfs_inode *ip, const char *name, char *value,
int *valuelenp, int flags, cred_t *cred);
int xfs_attr_set(struct xfs_inode *dp, const char *name, char *value,
int valuelen, int flags);
int xfs_attr_remove(struct xfs_inode *dp, const char *name, int flags);
int xfs_attr_list(struct xfs_inode *dp, char *buffer, int bufsize,
int flags, struct attrlist_cursor_kern *cursor);
int xfs_ioctl(struct xfs_inode *ip, struct file *filp,
int ioflags, unsigned int cmd, void __user *arg);
ssize_t xfs_read(struct xfs_inode *ip, struct kiocb *iocb,
const struct iovec *iovp, unsigned int segs,
loff_t *offset, int ioflags);
ssize_t xfs_sendfile(struct xfs_inode *ip, struct file *filp,
loff_t *offset, int ioflags, size_t count,
read_actor_t actor, void *target);
ssize_t xfs_splice_read(struct xfs_inode *ip, struct file *infilp,
loff_t *ppos, struct pipe_inode_info *pipe, size_t count,
int flags, int ioflags);
ssize_t xfs_splice_write(struct xfs_inode *ip,
struct pipe_inode_info *pipe, struct file *outfilp,
loff_t *ppos, size_t count, int flags, int ioflags);
ssize_t xfs_write(struct xfs_inode *xip, struct kiocb *iocb,
const struct iovec *iovp, unsigned int nsegs,
loff_t *offset, int ioflags);
int xfs_bmap(struct xfs_inode *ip, xfs_off_t offset, ssize_t count,
int flags, struct xfs_iomap *iomapp, int *niomaps);
void xfs_tosspages(struct xfs_inode *inode, xfs_off_t first,
xfs_off_t last, int fiopt);
int xfs_flushinval_pages(struct xfs_inode *ip, xfs_off_t first,
xfs_off_t last, int fiopt);
int xfs_flush_pages(struct xfs_inode *ip, xfs_off_t first,
xfs_off_t last, uint64_t flags, int fiopt);
#endif /* _XFS_VNODEOPS_H */