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:
commit
347c53dca7
|
@ -49,7 +49,6 @@ xfs-y += xfs_alloc.o \
|
|||
xfs_alloc_btree.o \
|
||||
xfs_attr.o \
|
||||
xfs_attr_leaf.o \
|
||||
xfs_behavior.o \
|
||||
xfs_bit.o \
|
||||
xfs_bmap.o \
|
||||
xfs_bmap_btree.o \
|
||||
|
@ -108,13 +107,11 @@ xfs-y += $(addprefix $(XFS_LINUX)/, \
|
|||
xfs_iops.o \
|
||||
xfs_lrw.o \
|
||||
xfs_super.o \
|
||||
xfs_vfs.o \
|
||||
xfs_vnode.o)
|
||||
|
||||
# Objects in support/
|
||||
xfs-y += $(addprefix support/, \
|
||||
debug.o \
|
||||
move.o \
|
||||
uuid.o)
|
||||
|
||||
xfs-$(CONFIG_XFS_TRACE) += support/ktrace.o
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
#include "xfs_error.h"
|
||||
#include "xfs_rw.h"
|
||||
#include "xfs_iomap.h"
|
||||
#include "xfs_vnodeops.h"
|
||||
#include <linux/mpage.h>
|
||||
#include <linux/pagevec.h>
|
||||
#include <linux/writeback.h>
|
||||
|
@ -139,9 +140,11 @@ xfs_destroy_ioend(
|
|||
next = bh->b_private;
|
||||
bh->b_end_io(bh, !ioend->io_error);
|
||||
}
|
||||
if (unlikely(ioend->io_error))
|
||||
vn_ioerror(ioend->io_vnode, ioend->io_error, __FILE__,__LINE__);
|
||||
vn_iowake(ioend->io_vnode);
|
||||
if (unlikely(ioend->io_error)) {
|
||||
vn_ioerror(XFS_I(ioend->io_inode), ioend->io_error,
|
||||
__FILE__,__LINE__);
|
||||
}
|
||||
vn_iowake(XFS_I(ioend->io_inode));
|
||||
mempool_free(ioend, xfs_ioend_pool);
|
||||
}
|
||||
|
||||
|
@ -156,14 +159,10 @@ STATIC void
|
|||
xfs_setfilesize(
|
||||
xfs_ioend_t *ioend)
|
||||
{
|
||||
xfs_inode_t *ip;
|
||||
xfs_inode_t *ip = XFS_I(ioend->io_inode);
|
||||
xfs_fsize_t isize;
|
||||
xfs_fsize_t bsize;
|
||||
|
||||
ip = xfs_vtoi(ioend->io_vnode);
|
||||
if (!ip)
|
||||
return;
|
||||
|
||||
ASSERT((ip->i_d.di_mode & S_IFMT) == S_IFREG);
|
||||
ASSERT(ioend->io_type != IOMAP_READ);
|
||||
|
||||
|
@ -181,7 +180,7 @@ xfs_setfilesize(
|
|||
ip->i_d.di_size = isize;
|
||||
ip->i_update_core = 1;
|
||||
ip->i_update_size = 1;
|
||||
mark_inode_dirty_sync(vn_to_inode(ioend->io_vnode));
|
||||
mark_inode_dirty_sync(ioend->io_inode);
|
||||
}
|
||||
|
||||
xfs_iunlock(ip, XFS_ILOCK_EXCL);
|
||||
|
@ -227,12 +226,12 @@ xfs_end_bio_unwritten(
|
|||
{
|
||||
xfs_ioend_t *ioend =
|
||||
container_of(work, xfs_ioend_t, io_work);
|
||||
bhv_vnode_t *vp = ioend->io_vnode;
|
||||
xfs_off_t offset = ioend->io_offset;
|
||||
size_t size = ioend->io_size;
|
||||
|
||||
if (likely(!ioend->io_error)) {
|
||||
bhv_vop_bmap(vp, offset, size, BMAPI_UNWRITTEN, NULL, NULL);
|
||||
xfs_bmap(XFS_I(ioend->io_inode), offset, size,
|
||||
BMAPI_UNWRITTEN, NULL, NULL);
|
||||
xfs_setfilesize(ioend);
|
||||
}
|
||||
xfs_destroy_ioend(ioend);
|
||||
|
@ -275,10 +274,10 @@ xfs_alloc_ioend(
|
|||
ioend->io_error = 0;
|
||||
ioend->io_list = NULL;
|
||||
ioend->io_type = type;
|
||||
ioend->io_vnode = vn_from_inode(inode);
|
||||
ioend->io_inode = inode;
|
||||
ioend->io_buffer_head = NULL;
|
||||
ioend->io_buffer_tail = NULL;
|
||||
atomic_inc(&ioend->io_vnode->v_iocount);
|
||||
atomic_inc(&XFS_I(ioend->io_inode)->i_iocount);
|
||||
ioend->io_offset = 0;
|
||||
ioend->io_size = 0;
|
||||
|
||||
|
@ -302,12 +301,13 @@ xfs_map_blocks(
|
|||
xfs_iomap_t *mapp,
|
||||
int flags)
|
||||
{
|
||||
bhv_vnode_t *vp = vn_from_inode(inode);
|
||||
xfs_inode_t *ip = XFS_I(inode);
|
||||
int error, nmaps = 1;
|
||||
|
||||
error = bhv_vop_bmap(vp, offset, count, flags, mapp, &nmaps);
|
||||
error = xfs_bmap(ip, offset, count,
|
||||
flags, mapp, &nmaps);
|
||||
if (!error && (flags & (BMAPI_WRITE|BMAPI_ALLOCATE)))
|
||||
VMODIFY(vp);
|
||||
xfs_iflags_set(ip, XFS_IMODIFIED);
|
||||
return -error;
|
||||
}
|
||||
|
||||
|
@ -497,7 +497,7 @@ xfs_cancel_ioend(
|
|||
unlock_buffer(bh);
|
||||
} while ((bh = next_bh) != NULL);
|
||||
|
||||
vn_iowake(ioend->io_vnode);
|
||||
vn_iowake(XFS_I(ioend->io_inode));
|
||||
mempool_free(ioend, xfs_ioend_pool);
|
||||
} while ((ioend = next) != NULL);
|
||||
}
|
||||
|
@ -1237,10 +1237,7 @@ xfs_vm_writepages(
|
|||
struct address_space *mapping,
|
||||
struct writeback_control *wbc)
|
||||
{
|
||||
struct bhv_vnode *vp = vn_from_inode(mapping->host);
|
||||
|
||||
if (VN_TRUNC(vp))
|
||||
VUNTRUNCATE(vp);
|
||||
xfs_iflags_clear(XFS_I(mapping->host), XFS_ITRUNCATED);
|
||||
return generic_writepages(mapping, wbc);
|
||||
}
|
||||
|
||||
|
@ -1317,7 +1314,6 @@ __xfs_get_blocks(
|
|||
int direct,
|
||||
bmapi_flags_t flags)
|
||||
{
|
||||
bhv_vnode_t *vp = vn_from_inode(inode);
|
||||
xfs_iomap_t iomap;
|
||||
xfs_off_t offset;
|
||||
ssize_t size;
|
||||
|
@ -1327,7 +1323,7 @@ __xfs_get_blocks(
|
|||
offset = (xfs_off_t)iblock << inode->i_blkbits;
|
||||
ASSERT(bh_result->b_size >= (1 << inode->i_blkbits));
|
||||
size = bh_result->b_size;
|
||||
error = bhv_vop_bmap(vp, offset, size,
|
||||
error = xfs_bmap(XFS_I(inode), offset, size,
|
||||
create ? flags : BMAPI_READ, &iomap, &niomap);
|
||||
if (error)
|
||||
return -error;
|
||||
|
@ -1475,13 +1471,13 @@ xfs_vm_direct_IO(
|
|||
{
|
||||
struct file *file = iocb->ki_filp;
|
||||
struct inode *inode = file->f_mapping->host;
|
||||
bhv_vnode_t *vp = vn_from_inode(inode);
|
||||
xfs_iomap_t iomap;
|
||||
int maps = 1;
|
||||
int error;
|
||||
ssize_t ret;
|
||||
|
||||
error = bhv_vop_bmap(vp, offset, 0, BMAPI_DEVICE, &iomap, &maps);
|
||||
error = xfs_bmap(XFS_I(inode), offset, 0,
|
||||
BMAPI_DEVICE, &iomap, &maps);
|
||||
if (error)
|
||||
return -error;
|
||||
|
||||
|
@ -1527,12 +1523,13 @@ xfs_vm_bmap(
|
|||
sector_t block)
|
||||
{
|
||||
struct inode *inode = (struct inode *)mapping->host;
|
||||
bhv_vnode_t *vp = vn_from_inode(inode);
|
||||
struct xfs_inode *ip = XFS_I(inode);
|
||||
|
||||
vn_trace_entry(vp, __FUNCTION__, (inst_t *)__return_address);
|
||||
bhv_vop_rwlock(vp, VRWLOCK_READ);
|
||||
bhv_vop_flush_pages(vp, (xfs_off_t)0, -1, 0, FI_REMAPF);
|
||||
bhv_vop_rwunlock(vp, VRWLOCK_READ);
|
||||
vn_trace_entry(XFS_I(inode), __FUNCTION__,
|
||||
(inst_t *)__return_address);
|
||||
xfs_rwlock(ip, VRWLOCK_READ);
|
||||
xfs_flush_pages(ip, (xfs_off_t)0, -1, 0, FI_REMAPF);
|
||||
xfs_rwunlock(ip, VRWLOCK_READ);
|
||||
return generic_block_bmap(mapping, block, xfs_get_blocks);
|
||||
}
|
||||
|
||||
|
|
|
@ -32,7 +32,7 @@ typedef struct xfs_ioend {
|
|||
unsigned int io_type; /* delalloc / unwritten */
|
||||
int io_error; /* I/O error code */
|
||||
atomic_t io_remaining; /* hold count */
|
||||
struct bhv_vnode *io_vnode; /* file being written to */
|
||||
struct inode *io_inode; /* file being written to */
|
||||
struct buffer_head *io_buffer_head;/* buffer linked list head */
|
||||
struct buffer_head *io_buffer_tail;/* buffer linked list tail */
|
||||
size_t io_size; /* size of the extent */
|
||||
|
|
|
@ -187,6 +187,19 @@ free_address(
|
|||
{
|
||||
a_list_t *aentry;
|
||||
|
||||
#ifdef CONFIG_XEN
|
||||
/*
|
||||
* Xen needs to be able to make sure it can get an exclusive
|
||||
* RO mapping of pages it wants to turn into a pagetable. If
|
||||
* a newly allocated page is also still being vmap()ed by xfs,
|
||||
* it will cause pagetable construction to fail. This is a
|
||||
* quick workaround to always eagerly unmap pages so that Xen
|
||||
* is happy.
|
||||
*/
|
||||
vunmap(addr);
|
||||
return;
|
||||
#endif
|
||||
|
||||
aentry = kmalloc(sizeof(a_list_t), GFP_NOWAIT);
|
||||
if (likely(aentry)) {
|
||||
spin_lock(&as_lock);
|
||||
|
@ -997,7 +1010,18 @@ xfs_buf_iodone_work(
|
|||
xfs_buf_t *bp =
|
||||
container_of(work, xfs_buf_t, b_iodone_work);
|
||||
|
||||
if (bp->b_iodone)
|
||||
/*
|
||||
* We can get an EOPNOTSUPP to ordered writes. Here we clear the
|
||||
* ordered flag and reissue them. Because we can't tell the higher
|
||||
* layers directly that they should not issue ordered I/O anymore, they
|
||||
* need to check if the ordered flag was cleared during I/O completion.
|
||||
*/
|
||||
if ((bp->b_error == EOPNOTSUPP) &&
|
||||
(bp->b_flags & (XBF_ORDERED|XBF_ASYNC)) == (XBF_ORDERED|XBF_ASYNC)) {
|
||||
XB_TRACE(bp, "ordered_retry", bp->b_iodone);
|
||||
bp->b_flags &= ~XBF_ORDERED;
|
||||
xfs_buf_iorequest(bp);
|
||||
} else if (bp->b_iodone)
|
||||
(*(bp->b_iodone))(bp);
|
||||
else if (bp->b_flags & XBF_ASYNC)
|
||||
xfs_buf_relse(bp);
|
||||
|
|
|
@ -17,12 +17,18 @@
|
|||
*/
|
||||
#include "xfs.h"
|
||||
#include "xfs_types.h"
|
||||
#include "xfs_dmapi.h"
|
||||
#include "xfs_inum.h"
|
||||
#include "xfs_log.h"
|
||||
#include "xfs_trans.h"
|
||||
#include "xfs_sb.h"
|
||||
#include "xfs_ag.h"
|
||||
#include "xfs_dmapi.h"
|
||||
#include "xfs_mount.h"
|
||||
#include "xfs_export.h"
|
||||
#include "xfs_vnodeops.h"
|
||||
#include "xfs_bmap_btree.h"
|
||||
#include "xfs_inode.h"
|
||||
#include "xfs_vfsops.h"
|
||||
|
||||
static struct dentry dotdot = { .d_name.name = "..", .d_name.len = 2, };
|
||||
|
||||
|
@ -96,9 +102,7 @@ xfs_fs_encode_fh(
|
|||
int len;
|
||||
int is64 = 0;
|
||||
#if XFS_BIG_INUMS
|
||||
bhv_vfs_t *vfs = vfs_from_sb(inode->i_sb);
|
||||
|
||||
if (!(vfs->vfs_flag & VFS_32BITINODES)) {
|
||||
if (!(XFS_M(inode->i_sb)->m_flags & XFS_MOUNT_SMALL_INUMS)) {
|
||||
/* filesystem may contain 64bit inode numbers */
|
||||
is64 = XFS_FILEID_TYPE_64FLAG;
|
||||
}
|
||||
|
@ -138,10 +142,9 @@ xfs_fs_get_dentry(
|
|||
bhv_vnode_t *vp;
|
||||
struct inode *inode;
|
||||
struct dentry *result;
|
||||
bhv_vfs_t *vfsp = vfs_from_sb(sb);
|
||||
int error;
|
||||
|
||||
error = bhv_vfs_vget(vfsp, &vp, (fid_t *)data);
|
||||
error = xfs_vget(XFS_M(sb), &vp, (fid_t *)data);
|
||||
if (error || vp == NULL)
|
||||
return ERR_PTR(-ESTALE) ;
|
||||
|
||||
|
@ -159,12 +162,11 @@ xfs_fs_get_parent(
|
|||
struct dentry *child)
|
||||
{
|
||||
int error;
|
||||
bhv_vnode_t *vp, *cvp;
|
||||
bhv_vnode_t *cvp;
|
||||
struct dentry *parent;
|
||||
|
||||
cvp = NULL;
|
||||
vp = vn_from_inode(child->d_inode);
|
||||
error = bhv_vop_lookup(vp, &dotdot, &cvp, 0, NULL, NULL);
|
||||
error = xfs_lookup(XFS_I(child->d_inode), &dotdot, &cvp);
|
||||
if (unlikely(error))
|
||||
return ERR_PTR(-error);
|
||||
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
#include "xfs_error.h"
|
||||
#include "xfs_rw.h"
|
||||
#include "xfs_ioctl32.h"
|
||||
#include "xfs_vnodeops.h"
|
||||
|
||||
#include <linux/dcache.h>
|
||||
#include <linux/smp_lock.h>
|
||||
|
@ -55,13 +56,12 @@ __xfs_file_read(
|
|||
loff_t pos)
|
||||
{
|
||||
struct file *file = iocb->ki_filp;
|
||||
bhv_vnode_t *vp = vn_from_inode(file->f_path.dentry->d_inode);
|
||||
|
||||
BUG_ON(iocb->ki_pos != pos);
|
||||
if (unlikely(file->f_flags & O_DIRECT))
|
||||
ioflags |= IO_ISDIRECT;
|
||||
return bhv_vop_read(vp, iocb, iov, nr_segs, &iocb->ki_pos,
|
||||
ioflags, NULL);
|
||||
return xfs_read(XFS_I(file->f_path.dentry->d_inode), iocb, iov,
|
||||
nr_segs, &iocb->ki_pos, ioflags);
|
||||
}
|
||||
|
||||
STATIC ssize_t
|
||||
|
@ -93,14 +93,12 @@ __xfs_file_write(
|
|||
loff_t pos)
|
||||
{
|
||||
struct file *file = iocb->ki_filp;
|
||||
struct inode *inode = file->f_mapping->host;
|
||||
bhv_vnode_t *vp = vn_from_inode(inode);
|
||||
|
||||
BUG_ON(iocb->ki_pos != pos);
|
||||
if (unlikely(file->f_flags & O_DIRECT))
|
||||
ioflags |= IO_ISDIRECT;
|
||||
return bhv_vop_write(vp, iocb, iov, nr_segs, &iocb->ki_pos,
|
||||
ioflags, NULL);
|
||||
return xfs_write(XFS_I(file->f_mapping->host), iocb, iov, nr_segs,
|
||||
&iocb->ki_pos, ioflags);
|
||||
}
|
||||
|
||||
STATIC ssize_t
|
||||
|
@ -131,8 +129,8 @@ xfs_file_splice_read(
|
|||
size_t len,
|
||||
unsigned int flags)
|
||||
{
|
||||
return bhv_vop_splice_read(vn_from_inode(infilp->f_path.dentry->d_inode),
|
||||
infilp, ppos, pipe, len, flags, 0, NULL);
|
||||
return xfs_splice_read(XFS_I(infilp->f_path.dentry->d_inode),
|
||||
infilp, ppos, pipe, len, flags, 0);
|
||||
}
|
||||
|
||||
STATIC ssize_t
|
||||
|
@ -143,9 +141,8 @@ xfs_file_splice_read_invis(
|
|||
size_t len,
|
||||
unsigned int flags)
|
||||
{
|
||||
return bhv_vop_splice_read(vn_from_inode(infilp->f_path.dentry->d_inode),
|
||||
infilp, ppos, pipe, len, flags, IO_INVIS,
|
||||
NULL);
|
||||
return xfs_splice_read(XFS_I(infilp->f_path.dentry->d_inode),
|
||||
infilp, ppos, pipe, len, flags, IO_INVIS);
|
||||
}
|
||||
|
||||
STATIC ssize_t
|
||||
|
@ -156,8 +153,8 @@ xfs_file_splice_write(
|
|||
size_t len,
|
||||
unsigned int flags)
|
||||
{
|
||||
return bhv_vop_splice_write(vn_from_inode(outfilp->f_path.dentry->d_inode),
|
||||
pipe, outfilp, ppos, len, flags, 0, NULL);
|
||||
return xfs_splice_write(XFS_I(outfilp->f_path.dentry->d_inode),
|
||||
pipe, outfilp, ppos, len, flags, 0);
|
||||
}
|
||||
|
||||
STATIC ssize_t
|
||||
|
@ -168,9 +165,8 @@ xfs_file_splice_write_invis(
|
|||
size_t len,
|
||||
unsigned int flags)
|
||||
{
|
||||
return bhv_vop_splice_write(vn_from_inode(outfilp->f_path.dentry->d_inode),
|
||||
pipe, outfilp, ppos, len, flags, IO_INVIS,
|
||||
NULL);
|
||||
return xfs_splice_write(XFS_I(outfilp->f_path.dentry->d_inode),
|
||||
pipe, outfilp, ppos, len, flags, IO_INVIS);
|
||||
}
|
||||
|
||||
STATIC int
|
||||
|
@ -180,7 +176,7 @@ xfs_file_open(
|
|||
{
|
||||
if (!(filp->f_flags & O_LARGEFILE) && i_size_read(inode) > MAX_NON_LFS)
|
||||
return -EFBIG;
|
||||
return -bhv_vop_open(vn_from_inode(inode), NULL);
|
||||
return -xfs_open(XFS_I(inode));
|
||||
}
|
||||
|
||||
STATIC int
|
||||
|
@ -188,11 +184,7 @@ xfs_file_release(
|
|||
struct inode *inode,
|
||||
struct file *filp)
|
||||
{
|
||||
bhv_vnode_t *vp = vn_from_inode(inode);
|
||||
|
||||
if (vp)
|
||||
return -bhv_vop_release(vp);
|
||||
return 0;
|
||||
return -xfs_release(XFS_I(inode));
|
||||
}
|
||||
|
||||
STATIC int
|
||||
|
@ -201,14 +193,13 @@ xfs_file_fsync(
|
|||
struct dentry *dentry,
|
||||
int datasync)
|
||||
{
|
||||
bhv_vnode_t *vp = vn_from_inode(dentry->d_inode);
|
||||
int flags = FSYNC_WAIT;
|
||||
|
||||
if (datasync)
|
||||
flags |= FSYNC_DATA;
|
||||
if (VN_TRUNC(vp))
|
||||
VUNTRUNCATE(vp);
|
||||
return -bhv_vop_fsync(vp, flags, NULL, (xfs_off_t)0, (xfs_off_t)-1);
|
||||
xfs_iflags_clear(XFS_I(dentry->d_inode), XFS_ITRUNCATED);
|
||||
return -xfs_fsync(XFS_I(dentry->d_inode), flags,
|
||||
(xfs_off_t)0, (xfs_off_t)-1);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_XFS_DMAPI
|
||||
|
@ -233,74 +224,30 @@ xfs_file_readdir(
|
|||
void *dirent,
|
||||
filldir_t filldir)
|
||||
{
|
||||
int error = 0;
|
||||
bhv_vnode_t *vp = vn_from_inode(filp->f_path.dentry->d_inode);
|
||||
uio_t uio;
|
||||
iovec_t iov;
|
||||
int eof = 0;
|
||||
caddr_t read_buf;
|
||||
int namelen, size = 0;
|
||||
size_t rlen = PAGE_CACHE_SIZE;
|
||||
xfs_off_t start_offset, curr_offset;
|
||||
xfs_dirent_t *dbp = NULL;
|
||||
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 */
|
||||
|
|
|
@ -16,66 +16,78 @@
|
|||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
#include "xfs.h"
|
||||
#include "xfs_vnodeops.h"
|
||||
|
||||
/*
|
||||
* The following six includes are needed so that we can include
|
||||
* xfs_inode.h. What a mess..
|
||||
*/
|
||||
#include "xfs_bmap_btree.h"
|
||||
#include "xfs_inum.h"
|
||||
#include "xfs_dir2.h"
|
||||
#include "xfs_dir2_sf.h"
|
||||
#include "xfs_attr_sf.h"
|
||||
#include "xfs_dinode.h"
|
||||
|
||||
#include "xfs_inode.h"
|
||||
|
||||
int fs_noerr(void) { return 0; }
|
||||
int fs_nosys(void) { return ENOSYS; }
|
||||
void fs_noval(void) { return; }
|
||||
|
||||
void
|
||||
fs_tosspages(
|
||||
bhv_desc_t *bdp,
|
||||
xfs_tosspages(
|
||||
xfs_inode_t *ip,
|
||||
xfs_off_t first,
|
||||
xfs_off_t last,
|
||||
int fiopt)
|
||||
{
|
||||
bhv_vnode_t *vp = BHV_TO_VNODE(bdp);
|
||||
struct inode *ip = vn_to_inode(vp);
|
||||
bhv_vnode_t *vp = XFS_ITOV(ip);
|
||||
struct inode *inode = vn_to_inode(vp);
|
||||
|
||||
if (VN_CACHED(vp))
|
||||
truncate_inode_pages(ip->i_mapping, first);
|
||||
truncate_inode_pages(inode->i_mapping, first);
|
||||
}
|
||||
|
||||
int
|
||||
fs_flushinval_pages(
|
||||
bhv_desc_t *bdp,
|
||||
xfs_flushinval_pages(
|
||||
xfs_inode_t *ip,
|
||||
xfs_off_t first,
|
||||
xfs_off_t last,
|
||||
int fiopt)
|
||||
{
|
||||
bhv_vnode_t *vp = BHV_TO_VNODE(bdp);
|
||||
struct inode *ip = vn_to_inode(vp);
|
||||
bhv_vnode_t *vp = XFS_ITOV(ip);
|
||||
struct inode *inode = vn_to_inode(vp);
|
||||
int ret = 0;
|
||||
|
||||
if (VN_CACHED(vp)) {
|
||||
if (VN_TRUNC(vp))
|
||||
VUNTRUNCATE(vp);
|
||||
ret = filemap_write_and_wait(ip->i_mapping);
|
||||
xfs_iflags_clear(ip, XFS_ITRUNCATED);
|
||||
ret = filemap_write_and_wait(inode->i_mapping);
|
||||
if (!ret)
|
||||
truncate_inode_pages(ip->i_mapping, first);
|
||||
truncate_inode_pages(inode->i_mapping, first);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
fs_flush_pages(
|
||||
bhv_desc_t *bdp,
|
||||
xfs_flush_pages(
|
||||
xfs_inode_t *ip,
|
||||
xfs_off_t first,
|
||||
xfs_off_t last,
|
||||
uint64_t flags,
|
||||
int fiopt)
|
||||
{
|
||||
bhv_vnode_t *vp = BHV_TO_VNODE(bdp);
|
||||
struct inode *ip = vn_to_inode(vp);
|
||||
bhv_vnode_t *vp = XFS_ITOV(ip);
|
||||
struct inode *inode = vn_to_inode(vp);
|
||||
int ret = 0;
|
||||
int ret2;
|
||||
|
||||
if (VN_DIRTY(vp)) {
|
||||
if (VN_TRUNC(vp))
|
||||
VUNTRUNCATE(vp);
|
||||
ret = filemap_fdatawrite(ip->i_mapping);
|
||||
xfs_iflags_clear(ip, XFS_ITRUNCATED);
|
||||
ret = filemap_fdatawrite(inode->i_mapping);
|
||||
if (flags & XFS_B_ASYNC)
|
||||
return ret;
|
||||
ret2 = filemap_fdatawait(ip->i_mapping);
|
||||
ret2 = filemap_fdatawait(inode->i_mapping);
|
||||
if (!ret)
|
||||
ret = ret2;
|
||||
}
|
||||
|
|
|
@ -18,12 +18,8 @@
|
|||
#ifndef __XFS_FS_SUBR_H__
|
||||
#define __XFS_FS_SUBR_H__
|
||||
|
||||
struct cred;
|
||||
extern int fs_noerr(void);
|
||||
extern int fs_nosys(void);
|
||||
extern void fs_noval(void);
|
||||
extern void fs_tosspages(bhv_desc_t *, xfs_off_t, xfs_off_t, int);
|
||||
extern int fs_flushinval_pages(bhv_desc_t *, xfs_off_t, xfs_off_t, int);
|
||||
extern int fs_flush_pages(bhv_desc_t *, xfs_off_t, xfs_off_t, uint64_t, int);
|
||||
|
||||
#endif /* __XFS_FS_SUBR_H__ */
|
||||
|
|
|
@ -19,11 +19,6 @@
|
|||
#include "xfs_cred.h"
|
||||
#include "xfs_sysctl.h"
|
||||
|
||||
/*
|
||||
* System memory size - used to scale certain data structures in XFS.
|
||||
*/
|
||||
unsigned long xfs_physmem;
|
||||
|
||||
/*
|
||||
* Tunable XFS parameters. xfs_params is required even when CONFIG_SYSCTL=n,
|
||||
* other XFS code uses these values. Times are measured in centisecs (i.e.
|
||||
|
|
|
@ -19,7 +19,6 @@
|
|||
#define __XFS_GLOBALS_H__
|
||||
|
||||
extern uint64_t xfs_panic_mask; /* set to cause more panics */
|
||||
extern unsigned long xfs_physmem;
|
||||
extern struct cred *sys_cred;
|
||||
|
||||
#endif /* __XFS_GLOBALS_H__ */
|
||||
|
|
|
@ -47,6 +47,7 @@
|
|||
#include "xfs_utils.h"
|
||||
#include "xfs_dfrag.h"
|
||||
#include "xfs_fsops.h"
|
||||
#include "xfs_vnodeops.h"
|
||||
|
||||
#include <linux/capability.h>
|
||||
#include <linux/dcache.h>
|
||||
|
@ -137,7 +138,8 @@ xfs_find_handle(
|
|||
vp = vn_from_inode(inode);
|
||||
|
||||
/* now we can grab the fsid */
|
||||
memcpy(&handle.ha_fsid, vp->v_vfsp->vfs_altfsid, sizeof(xfs_fsid_t));
|
||||
memcpy(&handle.ha_fsid, XFS_I(inode)->i_mount->m_fixedfsid,
|
||||
sizeof(xfs_fsid_t));
|
||||
hsize = sizeof(xfs_fsid_t);
|
||||
|
||||
if (cmd != XFS_IOC_PATH_TO_FSHANDLE) {
|
||||
|
@ -349,19 +351,44 @@ xfs_open_by_handle(
|
|||
return new_fd;
|
||||
}
|
||||
|
||||
/*
|
||||
* This is a copy from fs/namei.c:vfs_readlink(), except for removing it's
|
||||
* unused first argument.
|
||||
*/
|
||||
STATIC int
|
||||
do_readlink(
|
||||
char __user *buffer,
|
||||
int buflen,
|
||||
const char *link)
|
||||
{
|
||||
int len;
|
||||
|
||||
len = PTR_ERR(link);
|
||||
if (IS_ERR(link))
|
||||
goto out;
|
||||
|
||||
len = strlen(link);
|
||||
if (len > (unsigned) buflen)
|
||||
len = buflen;
|
||||
if (copy_to_user(buffer, link, len))
|
||||
len = -EFAULT;
|
||||
out:
|
||||
return len;
|
||||
}
|
||||
|
||||
|
||||
STATIC int
|
||||
xfs_readlink_by_handle(
|
||||
xfs_mount_t *mp,
|
||||
void __user *arg,
|
||||
struct inode *parinode)
|
||||
{
|
||||
int error;
|
||||
struct iovec aiov;
|
||||
struct uio auio;
|
||||
struct inode *inode;
|
||||
xfs_fsop_handlereq_t hreq;
|
||||
bhv_vnode_t *vp;
|
||||
__u32 olen;
|
||||
void *link;
|
||||
int error;
|
||||
|
||||
if (!capable(CAP_SYS_ADMIN))
|
||||
return -XFS_ERROR(EPERM);
|
||||
|
@ -374,29 +401,31 @@ xfs_readlink_by_handle(
|
|||
|
||||
/* Restrict this handle operation to symlinks only. */
|
||||
if (!S_ISLNK(inode->i_mode)) {
|
||||
VN_RELE(vp);
|
||||
return -XFS_ERROR(EINVAL);
|
||||
error = -XFS_ERROR(EINVAL);
|
||||
goto out_iput;
|
||||
}
|
||||
|
||||
if (copy_from_user(&olen, hreq.ohandlen, sizeof(__u32))) {
|
||||
VN_RELE(vp);
|
||||
return -XFS_ERROR(EFAULT);
|
||||
error = -XFS_ERROR(EFAULT);
|
||||
goto out_iput;
|
||||
}
|
||||
aiov.iov_len = olen;
|
||||
aiov.iov_base = hreq.ohandle;
|
||||
|
||||
auio.uio_iov = (struct kvec *)&aiov;
|
||||
auio.uio_iovcnt = 1;
|
||||
auio.uio_offset = 0;
|
||||
auio.uio_segflg = UIO_USERSPACE;
|
||||
auio.uio_resid = olen;
|
||||
link = kmalloc(MAXPATHLEN+1, GFP_KERNEL);
|
||||
if (!link)
|
||||
goto out_iput;
|
||||
|
||||
error = bhv_vop_readlink(vp, &auio, IO_INVIS, NULL);
|
||||
VN_RELE(vp);
|
||||
error = -xfs_readlink(XFS_I(inode), link);
|
||||
if (error)
|
||||
return -error;
|
||||
goto out_kfree;
|
||||
error = do_readlink(hreq.ohandle, olen, link);
|
||||
if (error)
|
||||
goto out_kfree;
|
||||
|
||||
return (olen - auio.uio_resid);
|
||||
out_kfree:
|
||||
kfree(link);
|
||||
out_iput:
|
||||
iput(inode);
|
||||
return error;
|
||||
}
|
||||
|
||||
STATIC int
|
||||
|
@ -409,7 +438,6 @@ xfs_fssetdm_by_handle(
|
|||
struct fsdmidata fsd;
|
||||
xfs_fsop_setdm_handlereq_t dmhreq;
|
||||
struct inode *inode;
|
||||
bhv_desc_t *bdp;
|
||||
bhv_vnode_t *vp;
|
||||
|
||||
if (!capable(CAP_MKNOD))
|
||||
|
@ -431,8 +459,8 @@ xfs_fssetdm_by_handle(
|
|||
return -XFS_ERROR(EFAULT);
|
||||
}
|
||||
|
||||
bdp = bhv_base_unlocked(VN_BHV_HEAD(vp));
|
||||
error = xfs_set_dmattrs(bdp, fsd.fsd_dmevmask, fsd.fsd_dmstate, NULL);
|
||||
error = xfs_set_dmattrs(xfs_vtoi(vp),
|
||||
fsd.fsd_dmevmask, fsd.fsd_dmstate);
|
||||
|
||||
VN_RELE(vp);
|
||||
if (error)
|
||||
|
@ -470,8 +498,8 @@ xfs_attrlist_by_handle(
|
|||
goto out_vn_rele;
|
||||
|
||||
cursor = (attrlist_cursor_kern_t *)&al_hreq.pos;
|
||||
error = bhv_vop_attr_list(vp, kbuf, al_hreq.buflen, al_hreq.flags,
|
||||
cursor, NULL);
|
||||
error = xfs_attr_list(XFS_I(inode), kbuf, al_hreq.buflen,
|
||||
al_hreq.flags, cursor);
|
||||
if (error)
|
||||
goto out_kfree;
|
||||
|
||||
|
@ -488,7 +516,7 @@ xfs_attrlist_by_handle(
|
|||
|
||||
STATIC int
|
||||
xfs_attrmulti_attr_get(
|
||||
bhv_vnode_t *vp,
|
||||
struct inode *inode,
|
||||
char *name,
|
||||
char __user *ubuf,
|
||||
__uint32_t *len,
|
||||
|
@ -503,7 +531,7 @@ xfs_attrmulti_attr_get(
|
|||
if (!kbuf)
|
||||
return ENOMEM;
|
||||
|
||||
error = bhv_vop_attr_get(vp, name, kbuf, len, flags, NULL);
|
||||
error = xfs_attr_get(XFS_I(inode), name, kbuf, len, flags, NULL);
|
||||
if (error)
|
||||
goto out_kfree;
|
||||
|
||||
|
@ -517,7 +545,7 @@ xfs_attrmulti_attr_get(
|
|||
|
||||
STATIC int
|
||||
xfs_attrmulti_attr_set(
|
||||
bhv_vnode_t *vp,
|
||||
struct inode *inode,
|
||||
char *name,
|
||||
const char __user *ubuf,
|
||||
__uint32_t len,
|
||||
|
@ -526,9 +554,9 @@ xfs_attrmulti_attr_set(
|
|||
char *kbuf;
|
||||
int error = EFAULT;
|
||||
|
||||
if (IS_RDONLY(&vp->v_inode))
|
||||
if (IS_RDONLY(inode))
|
||||
return -EROFS;
|
||||
if (IS_IMMUTABLE(&vp->v_inode) || IS_APPEND(&vp->v_inode))
|
||||
if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
|
||||
return EPERM;
|
||||
if (len > XATTR_SIZE_MAX)
|
||||
return EINVAL;
|
||||
|
@ -540,7 +568,7 @@ xfs_attrmulti_attr_set(
|
|||
if (copy_from_user(kbuf, ubuf, len))
|
||||
goto out_kfree;
|
||||
|
||||
error = bhv_vop_attr_set(vp, name, kbuf, len, flags, NULL);
|
||||
error = xfs_attr_set(XFS_I(inode), name, kbuf, len, flags);
|
||||
|
||||
out_kfree:
|
||||
kfree(kbuf);
|
||||
|
@ -549,15 +577,15 @@ xfs_attrmulti_attr_set(
|
|||
|
||||
STATIC int
|
||||
xfs_attrmulti_attr_remove(
|
||||
bhv_vnode_t *vp,
|
||||
struct inode *inode,
|
||||
char *name,
|
||||
__uint32_t flags)
|
||||
{
|
||||
if (IS_RDONLY(&vp->v_inode))
|
||||
if (IS_RDONLY(inode))
|
||||
return -EROFS;
|
||||
if (IS_IMMUTABLE(&vp->v_inode) || IS_APPEND(&vp->v_inode))
|
||||
if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
|
||||
return EPERM;
|
||||
return bhv_vop_attr_remove(vp, name, flags, NULL);
|
||||
return xfs_attr_remove(XFS_I(inode), name, flags);
|
||||
}
|
||||
|
||||
STATIC int
|
||||
|
@ -613,17 +641,17 @@ xfs_attrmulti_by_handle(
|
|||
|
||||
switch (ops[i].am_opcode) {
|
||||
case ATTR_OP_GET:
|
||||
ops[i].am_error = xfs_attrmulti_attr_get(vp,
|
||||
ops[i].am_error = xfs_attrmulti_attr_get(inode,
|
||||
attr_name, ops[i].am_attrvalue,
|
||||
&ops[i].am_length, ops[i].am_flags);
|
||||
break;
|
||||
case ATTR_OP_SET:
|
||||
ops[i].am_error = xfs_attrmulti_attr_set(vp,
|
||||
ops[i].am_error = xfs_attrmulti_attr_set(inode,
|
||||
attr_name, ops[i].am_attrvalue,
|
||||
ops[i].am_length, ops[i].am_flags);
|
||||
break;
|
||||
case ATTR_OP_REMOVE:
|
||||
ops[i].am_error = xfs_attrmulti_attr_remove(vp,
|
||||
ops[i].am_error = xfs_attrmulti_attr_remove(inode,
|
||||
attr_name, ops[i].am_flags);
|
||||
break;
|
||||
default:
|
||||
|
@ -649,7 +677,7 @@ xfs_attrmulti_by_handle(
|
|||
|
||||
STATIC int
|
||||
xfs_ioc_space(
|
||||
bhv_desc_t *bdp,
|
||||
struct xfs_inode *ip,
|
||||
struct inode *inode,
|
||||
struct file *filp,
|
||||
int flags,
|
||||
|
@ -680,38 +708,38 @@ xfs_ioc_xattr(
|
|||
unsigned int cmd,
|
||||
void __user *arg);
|
||||
|
||||
STATIC int
|
||||
xfs_ioc_fsgetxattr(
|
||||
xfs_inode_t *ip,
|
||||
int attr,
|
||||
void __user *arg);
|
||||
|
||||
STATIC int
|
||||
xfs_ioc_getbmap(
|
||||
bhv_desc_t *bdp,
|
||||
struct xfs_inode *ip,
|
||||
int flags,
|
||||
unsigned int cmd,
|
||||
void __user *arg);
|
||||
|
||||
STATIC int
|
||||
xfs_ioc_getbmapx(
|
||||
bhv_desc_t *bdp,
|
||||
struct xfs_inode *ip,
|
||||
void __user *arg);
|
||||
|
||||
int
|
||||
xfs_ioctl(
|
||||
bhv_desc_t *bdp,
|
||||
struct inode *inode,
|
||||
xfs_inode_t *ip,
|
||||
struct file *filp,
|
||||
int ioflags,
|
||||
unsigned int cmd,
|
||||
void __user *arg)
|
||||
{
|
||||
struct inode *inode = filp->f_path.dentry->d_inode;
|
||||
bhv_vnode_t *vp = vn_from_inode(inode);
|
||||
xfs_mount_t *mp = ip->i_mount;
|
||||
int error;
|
||||
bhv_vnode_t *vp;
|
||||
xfs_inode_t *ip;
|
||||
xfs_mount_t *mp;
|
||||
|
||||
vp = vn_from_inode(inode);
|
||||
|
||||
vn_trace_entry(vp, "xfs_ioctl", (inst_t *)__return_address);
|
||||
|
||||
ip = XFS_BHVTOI(bdp);
|
||||
mp = ip->i_mount;
|
||||
vn_trace_entry(XFS_I(inode), "xfs_ioctl", (inst_t *)__return_address);
|
||||
|
||||
switch (cmd) {
|
||||
|
||||
|
@ -731,7 +759,7 @@ xfs_ioctl(
|
|||
!capable(CAP_SYS_ADMIN))
|
||||
return -EPERM;
|
||||
|
||||
return xfs_ioc_space(bdp, inode, filp, ioflags, cmd, arg);
|
||||
return xfs_ioc_space(ip, inode, filp, ioflags, cmd, arg);
|
||||
|
||||
case XFS_IOC_DIOINFO: {
|
||||
struct dioattr da;
|
||||
|
@ -761,11 +789,13 @@ xfs_ioctl(
|
|||
case XFS_IOC_GETVERSION:
|
||||
return put_user(inode->i_generation, (int __user *)arg);
|
||||
|
||||
case XFS_IOC_FSGETXATTR:
|
||||
return xfs_ioc_fsgetxattr(ip, 0, arg);
|
||||
case XFS_IOC_FSGETXATTRA:
|
||||
return xfs_ioc_fsgetxattr(ip, 1, arg);
|
||||
case XFS_IOC_GETXFLAGS:
|
||||
case XFS_IOC_SETXFLAGS:
|
||||
case XFS_IOC_FSGETXATTR:
|
||||
case XFS_IOC_FSSETXATTR:
|
||||
case XFS_IOC_FSGETXATTRA:
|
||||
return xfs_ioc_xattr(vp, ip, filp, cmd, arg);
|
||||
|
||||
case XFS_IOC_FSSETDM: {
|
||||
|
@ -774,17 +804,17 @@ xfs_ioctl(
|
|||
if (copy_from_user(&dmi, arg, sizeof(dmi)))
|
||||
return -XFS_ERROR(EFAULT);
|
||||
|
||||
error = xfs_set_dmattrs(bdp, dmi.fsd_dmevmask, dmi.fsd_dmstate,
|
||||
NULL);
|
||||
error = xfs_set_dmattrs(ip, dmi.fsd_dmevmask,
|
||||
dmi.fsd_dmstate);
|
||||
return -error;
|
||||
}
|
||||
|
||||
case XFS_IOC_GETBMAP:
|
||||
case XFS_IOC_GETBMAPA:
|
||||
return xfs_ioc_getbmap(bdp, ioflags, cmd, arg);
|
||||
return xfs_ioc_getbmap(ip, ioflags, cmd, arg);
|
||||
|
||||
case XFS_IOC_GETBMAPX:
|
||||
return xfs_ioc_getbmapx(bdp, arg);
|
||||
return xfs_ioc_getbmapx(ip, arg);
|
||||
|
||||
case XFS_IOC_FD_TO_HANDLE:
|
||||
case XFS_IOC_PATH_TO_HANDLE:
|
||||
|
@ -944,7 +974,7 @@ xfs_ioctl(
|
|||
if (!capable(CAP_SYS_ADMIN))
|
||||
return -EPERM;
|
||||
|
||||
error = xfs_errortag_clearall(mp);
|
||||
error = xfs_errortag_clearall(mp, 1);
|
||||
return -error;
|
||||
|
||||
default:
|
||||
|
@ -954,7 +984,7 @@ xfs_ioctl(
|
|||
|
||||
STATIC int
|
||||
xfs_ioc_space(
|
||||
bhv_desc_t *bdp,
|
||||
struct xfs_inode *ip,
|
||||
struct inode *inode,
|
||||
struct file *filp,
|
||||
int ioflags,
|
||||
|
@ -982,7 +1012,7 @@ xfs_ioc_space(
|
|||
if (ioflags & IO_INVIS)
|
||||
attr_flags |= ATTR_DMI;
|
||||
|
||||
error = xfs_change_file_space(bdp, cmd, &bf, filp->f_pos,
|
||||
error = xfs_change_file_space(ip, cmd, &bf, filp->f_pos,
|
||||
NULL, attr_flags);
|
||||
return -error;
|
||||
}
|
||||
|
@ -1139,6 +1169,42 @@ xfs_di2lxflags(
|
|||
return flags;
|
||||
}
|
||||
|
||||
STATIC int
|
||||
xfs_ioc_fsgetxattr(
|
||||
xfs_inode_t *ip,
|
||||
int attr,
|
||||
void __user *arg)
|
||||
{
|
||||
struct fsxattr fa;
|
||||
|
||||
xfs_ilock(ip, XFS_ILOCK_SHARED);
|
||||
fa.fsx_xflags = xfs_ip2xflags(ip);
|
||||
fa.fsx_extsize = ip->i_d.di_extsize << ip->i_mount->m_sb.sb_blocklog;
|
||||
fa.fsx_projid = ip->i_d.di_projid;
|
||||
|
||||
if (attr) {
|
||||
if (ip->i_afp) {
|
||||
if (ip->i_afp->if_flags & XFS_IFEXTENTS)
|
||||
fa.fsx_nextents = ip->i_afp->if_bytes /
|
||||
sizeof(xfs_bmbt_rec_t);
|
||||
else
|
||||
fa.fsx_nextents = ip->i_d.di_anextents;
|
||||
} else
|
||||
fa.fsx_nextents = 0;
|
||||
} else {
|
||||
if (ip->i_df.if_flags & XFS_IFEXTENTS)
|
||||
fa.fsx_nextents = ip->i_df.if_bytes /
|
||||
sizeof(xfs_bmbt_rec_t);
|
||||
else
|
||||
fa.fsx_nextents = ip->i_d.di_nextents;
|
||||
}
|
||||
xfs_iunlock(ip, XFS_ILOCK_SHARED);
|
||||
|
||||
if (copy_to_user(arg, &fa, sizeof(fa)))
|
||||
return -EFAULT;
|
||||
return 0;
|
||||
}
|
||||
|
||||
STATIC int
|
||||
xfs_ioc_xattr(
|
||||
bhv_vnode_t *vp,
|
||||
|
@ -1158,27 +1224,6 @@ xfs_ioc_xattr(
|
|||
return -ENOMEM;
|
||||
|
||||
switch (cmd) {
|
||||
case XFS_IOC_FSGETXATTR: {
|
||||
vattr->va_mask = XFS_AT_XFLAGS | XFS_AT_EXTSIZE | \
|
||||
XFS_AT_NEXTENTS | XFS_AT_PROJID;
|
||||
error = bhv_vop_getattr(vp, vattr, 0, NULL);
|
||||
if (unlikely(error)) {
|
||||
error = -error;
|
||||
break;
|
||||
}
|
||||
|
||||
fa.fsx_xflags = vattr->va_xflags;
|
||||
fa.fsx_extsize = vattr->va_extsize;
|
||||
fa.fsx_nextents = vattr->va_nextents;
|
||||
fa.fsx_projid = vattr->va_projid;
|
||||
|
||||
if (copy_to_user(arg, &fa, sizeof(fa))) {
|
||||
error = -EFAULT;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case XFS_IOC_FSSETXATTR: {
|
||||
if (copy_from_user(&fa, arg, sizeof(fa))) {
|
||||
error = -EFAULT;
|
||||
|
@ -1194,34 +1239,13 @@ xfs_ioc_xattr(
|
|||
vattr->va_extsize = fa.fsx_extsize;
|
||||
vattr->va_projid = fa.fsx_projid;
|
||||
|
||||
error = bhv_vop_setattr(vp, vattr, attr_flags, NULL);
|
||||
error = xfs_setattr(ip, vattr, attr_flags, NULL);
|
||||
if (likely(!error))
|
||||
__vn_revalidate(vp, vattr); /* update flags */
|
||||
error = -error;
|
||||
break;
|
||||
}
|
||||
|
||||
case XFS_IOC_FSGETXATTRA: {
|
||||
vattr->va_mask = XFS_AT_XFLAGS | XFS_AT_EXTSIZE | \
|
||||
XFS_AT_ANEXTENTS | XFS_AT_PROJID;
|
||||
error = bhv_vop_getattr(vp, vattr, 0, NULL);
|
||||
if (unlikely(error)) {
|
||||
error = -error;
|
||||
break;
|
||||
}
|
||||
|
||||
fa.fsx_xflags = vattr->va_xflags;
|
||||
fa.fsx_extsize = vattr->va_extsize;
|
||||
fa.fsx_nextents = vattr->va_anextents;
|
||||
fa.fsx_projid = vattr->va_projid;
|
||||
|
||||
if (copy_to_user(arg, &fa, sizeof(fa))) {
|
||||
error = -EFAULT;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case XFS_IOC_GETXFLAGS: {
|
||||
flags = xfs_di2lxflags(ip->i_d.di_flags);
|
||||
if (copy_to_user(arg, &flags, sizeof(flags)))
|
||||
|
@ -1250,7 +1274,7 @@ xfs_ioc_xattr(
|
|||
vattr->va_xflags = xfs_merge_ioc_xflags(flags,
|
||||
xfs_ip2xflags(ip));
|
||||
|
||||
error = bhv_vop_setattr(vp, vattr, attr_flags, NULL);
|
||||
error = xfs_setattr(ip, vattr, attr_flags, NULL);
|
||||
if (likely(!error))
|
||||
__vn_revalidate(vp, vattr); /* update flags */
|
||||
error = -error;
|
||||
|
@ -1268,7 +1292,7 @@ xfs_ioc_xattr(
|
|||
|
||||
STATIC int
|
||||
xfs_ioc_getbmap(
|
||||
bhv_desc_t *bdp,
|
||||
struct xfs_inode *ip,
|
||||
int ioflags,
|
||||
unsigned int cmd,
|
||||
void __user *arg)
|
||||
|
@ -1287,7 +1311,7 @@ xfs_ioc_getbmap(
|
|||
if (ioflags & IO_INVIS)
|
||||
iflags |= BMV_IF_NO_DMAPI_READ;
|
||||
|
||||
error = xfs_getbmap(bdp, &bm, (struct getbmap __user *)arg+1, iflags);
|
||||
error = xfs_getbmap(ip, &bm, (struct getbmap __user *)arg+1, iflags);
|
||||
if (error)
|
||||
return -error;
|
||||
|
||||
|
@ -1298,7 +1322,7 @@ xfs_ioc_getbmap(
|
|||
|
||||
STATIC int
|
||||
xfs_ioc_getbmapx(
|
||||
bhv_desc_t *bdp,
|
||||
struct xfs_inode *ip,
|
||||
void __user *arg)
|
||||
{
|
||||
struct getbmapx bmx;
|
||||
|
@ -1325,7 +1349,7 @@ xfs_ioc_getbmapx(
|
|||
|
||||
iflags |= BMV_IF_EXTENDED;
|
||||
|
||||
error = xfs_getbmap(bdp, &bm, (struct getbmapx __user *)arg+1, iflags);
|
||||
error = xfs_getbmap(ip, &bm, (struct getbmapx __user *)arg+1, iflags);
|
||||
if (error)
|
||||
return -error;
|
||||
|
||||
|
|
|
@ -43,6 +43,7 @@
|
|||
#include "xfs_itable.h"
|
||||
#include "xfs_error.h"
|
||||
#include "xfs_dfrag.h"
|
||||
#include "xfs_vnodeops.h"
|
||||
|
||||
#define _NATIVE_IOC(cmd, type) \
|
||||
_IOC(_IOC_DIR(cmd), _IOC_TYPE(cmd), _IOC_NR(cmd), sizeof(type))
|
||||
|
@ -370,7 +371,6 @@ xfs_compat_ioctl(
|
|||
unsigned long arg)
|
||||
{
|
||||
struct inode *inode = file->f_path.dentry->d_inode;
|
||||
bhv_vnode_t *vp = vn_from_inode(inode);
|
||||
int error;
|
||||
|
||||
switch (cmd) {
|
||||
|
@ -443,7 +443,7 @@ xfs_compat_ioctl(
|
|||
case XFS_IOC_FSBULKSTAT_SINGLE_32:
|
||||
case XFS_IOC_FSINUMBERS_32:
|
||||
cmd = _NATIVE_IOC(cmd, struct xfs_fsop_bulkreq);
|
||||
return xfs_ioc_bulkstat_compat(XFS_BHVTOI(VNHEAD(vp))->i_mount,
|
||||
return xfs_ioc_bulkstat_compat(XFS_I(inode)->i_mount,
|
||||
cmd, (void __user*)arg);
|
||||
case XFS_IOC_FD_TO_HANDLE_32:
|
||||
case XFS_IOC_PATH_TO_HANDLE_32:
|
||||
|
@ -457,8 +457,8 @@ xfs_compat_ioctl(
|
|||
return -ENOIOCTLCMD;
|
||||
}
|
||||
|
||||
error = bhv_vop_ioctl(vp, inode, file, mode, cmd, (void __user *)arg);
|
||||
VMODIFY(vp);
|
||||
error = xfs_ioctl(XFS_I(inode), file, mode, cmd, (void __user *)arg);
|
||||
xfs_iflags_set(XFS_I(inode), XFS_IMODIFIED);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
|
|
@ -46,28 +46,13 @@
|
|||
#include "xfs_attr.h"
|
||||
#include "xfs_buf_item.h"
|
||||
#include "xfs_utils.h"
|
||||
#include "xfs_vnodeops.h"
|
||||
|
||||
#include <linux/capability.h>
|
||||
#include <linux/xattr.h>
|
||||
#include <linux/namei.h>
|
||||
#include <linux/security.h>
|
||||
|
||||
/*
|
||||
* Get a XFS inode from a given vnode.
|
||||
*/
|
||||
xfs_inode_t *
|
||||
xfs_vtoi(
|
||||
bhv_vnode_t *vp)
|
||||
{
|
||||
bhv_desc_t *bdp;
|
||||
|
||||
bdp = bhv_lookup_range(VN_BHV_HEAD(vp),
|
||||
VNODE_POSITION_XFS, VNODE_POSITION_XFS);
|
||||
if (unlikely(bdp == NULL))
|
||||
return NULL;
|
||||
return XFS_BHVTOI(bdp);
|
||||
}
|
||||
|
||||
/*
|
||||
* Bring the atime in the XFS inode uptodate.
|
||||
* Used before logging the inode to disk or when the Linux inode goes away.
|
||||
|
@ -80,9 +65,8 @@ xfs_synchronize_atime(
|
|||
|
||||
vp = XFS_ITOV_NULL(ip);
|
||||
if (vp) {
|
||||
struct inode *inode = &vp->v_inode;
|
||||
ip->i_d.di_atime.t_sec = (__int32_t)inode->i_atime.tv_sec;
|
||||
ip->i_d.di_atime.t_nsec = (__int32_t)inode->i_atime.tv_nsec;
|
||||
ip->i_d.di_atime.t_sec = (__int32_t)vp->i_atime.tv_sec;
|
||||
ip->i_d.di_atime.t_nsec = (__int32_t)vp->i_atime.tv_nsec;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -195,18 +179,19 @@ xfs_ichgtime_fast(
|
|||
*/
|
||||
STATIC void
|
||||
xfs_validate_fields(
|
||||
struct inode *ip,
|
||||
bhv_vattr_t *vattr)
|
||||
struct inode *inode)
|
||||
{
|
||||
vattr->va_mask = XFS_AT_NLINK|XFS_AT_SIZE|XFS_AT_NBLOCKS;
|
||||
if (!bhv_vop_getattr(vn_from_inode(ip), vattr, ATTR_LAZY, NULL)) {
|
||||
ip->i_nlink = vattr->va_nlink;
|
||||
ip->i_blocks = vattr->va_nblocks;
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -26,11 +26,15 @@ extern const struct file_operations xfs_file_operations;
|
|||
extern const struct file_operations xfs_dir_file_operations;
|
||||
extern const struct file_operations xfs_invis_file_operations;
|
||||
|
||||
extern int xfs_ioctl(struct bhv_desc *, struct inode *, struct file *,
|
||||
int, unsigned int, void __user *);
|
||||
|
||||
struct xfs_inode;
|
||||
extern void xfs_ichgtime(struct xfs_inode *, int);
|
||||
extern void xfs_ichgtime_fast(struct xfs_inode *, struct inode *, int);
|
||||
|
||||
#define xfs_vtoi(vp) \
|
||||
((struct xfs_inode *)vn_to_inode(vp)->i_private)
|
||||
|
||||
#define XFS_I(inode) \
|
||||
((struct xfs_inode *)(inode)->i_private)
|
||||
|
||||
#endif /* __XFS_IOPS_H__ */
|
||||
|
|
|
@ -51,7 +51,6 @@
|
|||
|
||||
#include <support/ktrace.h>
|
||||
#include <support/debug.h>
|
||||
#include <support/move.h>
|
||||
#include <support/uuid.h>
|
||||
|
||||
#include <linux/mm.h>
|
||||
|
@ -75,6 +74,7 @@
|
|||
#include <linux/cpu.h>
|
||||
#include <linux/notifier.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/log2.h>
|
||||
|
||||
#include <asm/page.h>
|
||||
#include <asm/div64.h>
|
||||
|
@ -83,7 +83,6 @@
|
|||
#include <asm/byteorder.h>
|
||||
#include <asm/unaligned.h>
|
||||
|
||||
#include <xfs_behavior.h>
|
||||
#include <xfs_vfs.h>
|
||||
#include <xfs_cred.h>
|
||||
#include <xfs_vnode.h>
|
||||
|
|
|
@ -48,6 +48,7 @@
|
|||
#include "xfs_buf_item.h"
|
||||
#include "xfs_utils.h"
|
||||
#include "xfs_iomap.h"
|
||||
#include "xfs_vnodeops.h"
|
||||
|
||||
#include <linux/capability.h>
|
||||
#include <linux/writeback.h>
|
||||
|
@ -169,27 +170,22 @@ xfs_iozero(
|
|||
|
||||
ssize_t /* bytes read, or (-) error */
|
||||
xfs_read(
|
||||
bhv_desc_t *bdp,
|
||||
xfs_inode_t *ip,
|
||||
struct kiocb *iocb,
|
||||
const struct iovec *iovp,
|
||||
unsigned int segs,
|
||||
loff_t *offset,
|
||||
int ioflags,
|
||||
cred_t *credp)
|
||||
int ioflags)
|
||||
{
|
||||
struct file *file = iocb->ki_filp;
|
||||
struct inode *inode = file->f_mapping->host;
|
||||
bhv_vnode_t *vp = XFS_ITOV(ip);
|
||||
xfs_mount_t *mp = ip->i_mount;
|
||||
size_t size = 0;
|
||||
ssize_t ret = 0;
|
||||
xfs_fsize_t n;
|
||||
xfs_inode_t *ip;
|
||||
xfs_mount_t *mp;
|
||||
bhv_vnode_t *vp;
|
||||
unsigned long seg;
|
||||
|
||||
ip = XFS_BHVTOI(bdp);
|
||||
vp = BHV_TO_VNODE(bdp);
|
||||
mp = ip->i_mount;
|
||||
|
||||
XFS_STATS_INC(xs_read_calls);
|
||||
|
||||
|
@ -234,13 +230,11 @@ xfs_read(
|
|||
mutex_lock(&inode->i_mutex);
|
||||
xfs_ilock(ip, XFS_IOLOCK_SHARED);
|
||||
|
||||
if (DM_EVENT_ENABLED(vp->v_vfsp, ip, DM_EVENT_READ) &&
|
||||
!(ioflags & IO_INVIS)) {
|
||||
if (DM_EVENT_ENABLED(ip, DM_EVENT_READ) && !(ioflags & IO_INVIS)) {
|
||||
bhv_vrwlock_t locktype = VRWLOCK_READ;
|
||||
int dmflags = FILP_DELAY_FLAG(file) | DM_SEM_FLAG_RD(ioflags);
|
||||
|
||||
ret = -XFS_SEND_DATA(mp, DM_EVENT_READ,
|
||||
BHV_TO_VNODE(bdp), *offset, size,
|
||||
ret = -XFS_SEND_DATA(mp, DM_EVENT_READ, vp, *offset, size,
|
||||
dmflags, &locktype);
|
||||
if (ret) {
|
||||
xfs_iunlock(ip, XFS_IOLOCK_SHARED);
|
||||
|
@ -252,8 +246,9 @@ xfs_read(
|
|||
|
||||
if (unlikely(ioflags & IO_ISDIRECT)) {
|
||||
if (VN_CACHED(vp))
|
||||
ret = bhv_vop_flushinval_pages(vp, ctooff(offtoct(*offset)),
|
||||
-1, FI_REMAPF_LOCKED);
|
||||
ret = xfs_flushinval_pages(ip,
|
||||
ctooff(offtoct(*offset)),
|
||||
-1, FI_REMAPF_LOCKED);
|
||||
mutex_unlock(&inode->i_mutex);
|
||||
if (ret) {
|
||||
xfs_iunlock(ip, XFS_IOLOCK_SHARED);
|
||||
|
@ -277,16 +272,15 @@ xfs_read(
|
|||
|
||||
ssize_t
|
||||
xfs_splice_read(
|
||||
bhv_desc_t *bdp,
|
||||
xfs_inode_t *ip,
|
||||
struct file *infilp,
|
||||
loff_t *ppos,
|
||||
struct pipe_inode_info *pipe,
|
||||
size_t count,
|
||||
int flags,
|
||||
int ioflags,
|
||||
cred_t *credp)
|
||||
int ioflags)
|
||||
{
|
||||
xfs_inode_t *ip = XFS_BHVTOI(bdp);
|
||||
bhv_vnode_t *vp = XFS_ITOV(ip);
|
||||
xfs_mount_t *mp = ip->i_mount;
|
||||
ssize_t ret;
|
||||
|
||||
|
@ -296,13 +290,11 @@ xfs_splice_read(
|
|||
|
||||
xfs_ilock(ip, XFS_IOLOCK_SHARED);
|
||||
|
||||
if (DM_EVENT_ENABLED(BHV_TO_VNODE(bdp)->v_vfsp, ip, DM_EVENT_READ) &&
|
||||
(!(ioflags & IO_INVIS))) {
|
||||
if (DM_EVENT_ENABLED(ip, DM_EVENT_READ) && !(ioflags & IO_INVIS)) {
|
||||
bhv_vrwlock_t locktype = VRWLOCK_READ;
|
||||
int error;
|
||||
|
||||
error = XFS_SEND_DATA(mp, DM_EVENT_READ, BHV_TO_VNODE(bdp),
|
||||
*ppos, count,
|
||||
error = XFS_SEND_DATA(mp, DM_EVENT_READ, vp, *ppos, count,
|
||||
FILP_DELAY_FLAG(infilp), &locktype);
|
||||
if (error) {
|
||||
xfs_iunlock(ip, XFS_IOLOCK_SHARED);
|
||||
|
@ -321,16 +313,15 @@ xfs_splice_read(
|
|||
|
||||
ssize_t
|
||||
xfs_splice_write(
|
||||
bhv_desc_t *bdp,
|
||||
xfs_inode_t *ip,
|
||||
struct pipe_inode_info *pipe,
|
||||
struct file *outfilp,
|
||||
loff_t *ppos,
|
||||
size_t count,
|
||||
int flags,
|
||||
int ioflags,
|
||||
cred_t *credp)
|
||||
int ioflags)
|
||||
{
|
||||
xfs_inode_t *ip = XFS_BHVTOI(bdp);
|
||||
bhv_vnode_t *vp = XFS_ITOV(ip);
|
||||
xfs_mount_t *mp = ip->i_mount;
|
||||
xfs_iocore_t *io = &ip->i_iocore;
|
||||
ssize_t ret;
|
||||
|
@ -343,13 +334,11 @@ xfs_splice_write(
|
|||
|
||||
xfs_ilock(ip, XFS_IOLOCK_EXCL);
|
||||
|
||||
if (DM_EVENT_ENABLED(BHV_TO_VNODE(bdp)->v_vfsp, ip, DM_EVENT_WRITE) &&
|
||||
(!(ioflags & IO_INVIS))) {
|
||||
if (DM_EVENT_ENABLED(ip, DM_EVENT_WRITE) && !(ioflags & IO_INVIS)) {
|
||||
bhv_vrwlock_t locktype = VRWLOCK_WRITE;
|
||||
int error;
|
||||
|
||||
error = XFS_SEND_DATA(mp, DM_EVENT_WRITE, BHV_TO_VNODE(bdp),
|
||||
*ppos, count,
|
||||
error = XFS_SEND_DATA(mp, DM_EVENT_WRITE, vp, *ppos, count,
|
||||
FILP_DELAY_FLAG(outfilp), &locktype);
|
||||
if (error) {
|
||||
xfs_iunlock(ip, XFS_IOLOCK_EXCL);
|
||||
|
@ -583,24 +572,22 @@ 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);
|
||||
|
|
|
@ -18,8 +18,6 @@
|
|||
#ifndef __XFS_LRW_H__
|
||||
#define __XFS_LRW_H__
|
||||
|
||||
struct bhv_desc;
|
||||
struct bhv_vnode;
|
||||
struct xfs_mount;
|
||||
struct xfs_iocore;
|
||||
struct xfs_inode;
|
||||
|
@ -71,30 +69,11 @@ extern void xfs_inval_cached_trace(struct xfs_iocore *,
|
|||
#define xfs_inval_cached_trace(io, offset, len, first, last)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Maximum count of bmaps used by read and write paths.
|
||||
*/
|
||||
#define XFS_MAX_RW_NBMAPS 4
|
||||
|
||||
extern int xfs_bmap(struct bhv_desc *, xfs_off_t, ssize_t, int,
|
||||
struct xfs_iomap *, int *);
|
||||
extern int xfsbdstrat(struct xfs_mount *, struct xfs_buf *);
|
||||
extern int xfs_bdstrat_cb(struct xfs_buf *);
|
||||
extern int xfs_dev_is_read_only(struct xfs_mount *, char *);
|
||||
|
||||
extern int xfs_zero_eof(struct bhv_vnode *, struct xfs_iocore *, xfs_off_t,
|
||||
extern int xfs_zero_eof(struct inode *, struct xfs_iocore *, xfs_off_t,
|
||||
xfs_fsize_t);
|
||||
extern ssize_t xfs_read(struct bhv_desc *, struct kiocb *,
|
||||
const struct iovec *, unsigned int,
|
||||
loff_t *, int, struct cred *);
|
||||
extern ssize_t xfs_write(struct bhv_desc *, struct kiocb *,
|
||||
const struct iovec *, unsigned int,
|
||||
loff_t *, int, struct cred *);
|
||||
extern ssize_t xfs_splice_read(struct bhv_desc *, struct file *, loff_t *,
|
||||
struct pipe_inode_info *, size_t, int, int,
|
||||
struct cred *);
|
||||
extern ssize_t xfs_splice_write(struct bhv_desc *, struct pipe_inode_info *,
|
||||
struct file *, loff_t *, size_t, int, int,
|
||||
struct cred *);
|
||||
|
||||
#endif /* __XFS_LRW_H__ */
|
||||
|
|
|
@ -46,6 +46,8 @@
|
|||
#include "xfs_attr.h"
|
||||
#include "xfs_buf_item.h"
|
||||
#include "xfs_utils.h"
|
||||
#include "xfs_vnodeops.h"
|
||||
#include "xfs_vfsops.h"
|
||||
#include "xfs_version.h"
|
||||
|
||||
#include <linux/namei.h>
|
||||
|
@ -196,23 +198,20 @@ xfs_revalidate_inode(
|
|||
inode->i_flags |= S_NOATIME;
|
||||
else
|
||||
inode->i_flags &= ~S_NOATIME;
|
||||
vp->v_flag &= ~VMODIFIED;
|
||||
xfs_iflags_clear(ip, XFS_IMODIFIED);
|
||||
}
|
||||
|
||||
void
|
||||
xfs_initialize_vnode(
|
||||
bhv_desc_t *bdp,
|
||||
struct xfs_mount *mp,
|
||||
bhv_vnode_t *vp,
|
||||
bhv_desc_t *inode_bhv,
|
||||
int unlock)
|
||||
struct xfs_inode *ip)
|
||||
{
|
||||
xfs_inode_t *ip = XFS_BHVTOI(inode_bhv);
|
||||
struct inode *inode = vn_to_inode(vp);
|
||||
|
||||
if (!inode_bhv->bd_vobj) {
|
||||
vp->v_vfsp = bhvtovfs(bdp);
|
||||
bhv_desc_init(inode_bhv, ip, vp, &xfs_vnodeops);
|
||||
bhv_insert(VN_BHV_HEAD(vp), inode_bhv);
|
||||
if (!ip->i_vnode) {
|
||||
ip->i_vnode = vp;
|
||||
inode->i_private = ip;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -222,8 +221,8 @@ xfs_initialize_vnode(
|
|||
* second time once the inode is properly set up, and then we can
|
||||
* finish our work.
|
||||
*/
|
||||
if (ip->i_d.di_mode != 0 && unlock && (inode->i_state & I_NEW)) {
|
||||
xfs_revalidate_inode(XFS_BHVTOM(bdp), vp, ip);
|
||||
if (ip->i_d.di_mode != 0 && (inode->i_state & I_NEW)) {
|
||||
xfs_revalidate_inode(mp, vp, ip);
|
||||
xfs_set_inodeops(inode);
|
||||
|
||||
xfs_iflags_clear(ip, XFS_INEW);
|
||||
|
@ -409,19 +408,22 @@ xfs_fs_write_inode(
|
|||
struct inode *inode,
|
||||
int sync)
|
||||
{
|
||||
bhv_vnode_t *vp = vn_from_inode(inode);
|
||||
int error = 0, flags = FLUSH_INODE;
|
||||
|
||||
if (vp) {
|
||||
vn_trace_entry(vp, __FUNCTION__, (inst_t *)__return_address);
|
||||
if (sync) {
|
||||
filemap_fdatawait(inode->i_mapping);
|
||||
flags |= FLUSH_SYNC;
|
||||
}
|
||||
error = bhv_vop_iflush(vp, flags);
|
||||
if (error == EAGAIN)
|
||||
error = sync? bhv_vop_iflush(vp, flags | FLUSH_LOG) : 0;
|
||||
vn_trace_entry(XFS_I(inode), __FUNCTION__,
|
||||
(inst_t *)__return_address);
|
||||
if (sync) {
|
||||
filemap_fdatawait(inode->i_mapping);
|
||||
flags |= FLUSH_SYNC;
|
||||
}
|
||||
error = xfs_inode_flush(XFS_I(inode), flags);
|
||||
/*
|
||||
* if we failed to write out the inode then mark
|
||||
* it dirty again so we'll try again later.
|
||||
*/
|
||||
if (error)
|
||||
mark_inode_dirty_sync(inode);
|
||||
|
||||
return -error;
|
||||
}
|
||||
|
||||
|
@ -429,35 +431,27 @@ STATIC void
|
|||
xfs_fs_clear_inode(
|
||||
struct inode *inode)
|
||||
{
|
||||
bhv_vnode_t *vp = vn_from_inode(inode);
|
||||
|
||||
vn_trace_entry(vp, __FUNCTION__, (inst_t *)__return_address);
|
||||
|
||||
XFS_STATS_INC(vn_rele);
|
||||
XFS_STATS_INC(vn_remove);
|
||||
XFS_STATS_INC(vn_reclaim);
|
||||
XFS_STATS_DEC(vn_active);
|
||||
xfs_inode_t *ip = XFS_I(inode);
|
||||
|
||||
/*
|
||||
* This can happen because xfs_iget_core calls xfs_idestroy if we
|
||||
* ip can be null when xfs_iget_core calls xfs_idestroy if we
|
||||
* find an inode with di_mode == 0 but without IGET_CREATE set.
|
||||
*/
|
||||
if (VNHEAD(vp))
|
||||
bhv_vop_inactive(vp, NULL);
|
||||
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();
|
||||
|
|
|
@ -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__ */
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -21,68 +21,25 @@
|
|||
#include <linux/vfs.h>
|
||||
#include "xfs_fs.h"
|
||||
|
||||
struct bhv_vfs;
|
||||
struct bhv_vnode;
|
||||
struct inode;
|
||||
|
||||
struct fid;
|
||||
struct cred;
|
||||
struct seq_file;
|
||||
struct super_block;
|
||||
struct xfs_inode;
|
||||
struct xfs_mount;
|
||||
struct xfs_mount_args;
|
||||
|
||||
typedef struct kstatfs bhv_statvfs_t;
|
||||
|
||||
typedef struct bhv_vfs_sync_work {
|
||||
struct list_head w_list;
|
||||
struct bhv_vfs *w_vfs;
|
||||
struct xfs_mount *w_mount;
|
||||
void *w_data; /* syncer routine argument */
|
||||
void (*w_syncer)(struct bhv_vfs *, void *);
|
||||
void (*w_syncer)(struct xfs_mount *, void *);
|
||||
} bhv_vfs_sync_work_t;
|
||||
|
||||
typedef struct bhv_vfs {
|
||||
u_int vfs_flag; /* flags */
|
||||
xfs_fsid_t vfs_fsid; /* file system ID */
|
||||
xfs_fsid_t *vfs_altfsid; /* An ID fixed for life of FS */
|
||||
bhv_head_t vfs_bh; /* head of vfs behavior chain */
|
||||
struct super_block *vfs_super; /* generic superblock pointer */
|
||||
struct task_struct *vfs_sync_task; /* generalised sync thread */
|
||||
bhv_vfs_sync_work_t vfs_sync_work; /* work item for VFS_SYNC */
|
||||
struct list_head vfs_sync_list; /* sync thread work item list */
|
||||
spinlock_t vfs_sync_lock; /* work item list lock */
|
||||
int vfs_sync_seq; /* sync thread generation no. */
|
||||
wait_queue_head_t vfs_wait_single_sync_task;
|
||||
} bhv_vfs_t;
|
||||
|
||||
#define bhvtovfs(bdp) ( (struct bhv_vfs *)BHV_VOBJ(bdp) )
|
||||
#define bhvtovfsops(bdp) ( (struct bhv_vfsops *)BHV_OPS(bdp) )
|
||||
#define VFS_BHVHEAD(vfs) ( &(vfs)->vfs_bh )
|
||||
#define VFS_REMOVEBHV(vfs, bdp) ( bhv_remove(VFS_BHVHEAD(vfs), bdp) )
|
||||
|
||||
#define VFS_POSITION_BASE BHV_POSITION_BASE /* chain bottom */
|
||||
#define VFS_POSITION_TOP BHV_POSITION_TOP /* chain top */
|
||||
#define VFS_POSITION_INVALID BHV_POSITION_INVALID /* invalid pos. num */
|
||||
|
||||
typedef enum {
|
||||
VFS_BHV_UNKNOWN, /* not specified */
|
||||
VFS_BHV_XFS, /* xfs */
|
||||
VFS_BHV_DM, /* data migration */
|
||||
VFS_BHV_QM, /* quota manager */
|
||||
VFS_BHV_IO, /* IO path */
|
||||
VFS_BHV_END /* housekeeping end-of-range */
|
||||
} bhv_vfs_type_t;
|
||||
|
||||
#define VFS_POSITION_XFS (BHV_POSITION_BASE)
|
||||
#define VFS_POSITION_DM (VFS_POSITION_BASE+10)
|
||||
#define VFS_POSITION_QM (VFS_POSITION_BASE+20)
|
||||
#define VFS_POSITION_IO (VFS_POSITION_BASE+30)
|
||||
|
||||
#define VFS_RDONLY 0x0001 /* read-only vfs */
|
||||
#define VFS_GRPID 0x0002 /* group-ID assigned from directory */
|
||||
#define VFS_DMI 0x0004 /* filesystem has the DMI enabled */
|
||||
/* ---- VFS_UMOUNT ---- 0x0008 -- unneeded, fixed via kthread APIs */
|
||||
#define VFS_32BITINODES 0x0010 /* do not use inums above 32 bits */
|
||||
#define VFS_END 0x0010 /* max flag */
|
||||
|
||||
#define SYNC_ATTR 0x0001 /* sync attributes */
|
||||
#define SYNC_CLOSE 0x0002 /* close file system down */
|
||||
#define SYNC_DELWRI 0x0004 /* look at delayed writes */
|
||||
|
@ -115,118 +72,7 @@ typedef enum {
|
|||
#define SHUTDOWN_REMOTE_REQ 0x0010 /* shutdown came from remote cell */
|
||||
#define SHUTDOWN_DEVICE_REQ 0x0020 /* failed all paths to the device */
|
||||
|
||||
typedef int (*vfs_mount_t)(bhv_desc_t *,
|
||||
struct xfs_mount_args *, struct cred *);
|
||||
typedef int (*vfs_parseargs_t)(bhv_desc_t *, char *,
|
||||
struct xfs_mount_args *, int);
|
||||
typedef int (*vfs_showargs_t)(bhv_desc_t *, struct seq_file *);
|
||||
typedef int (*vfs_unmount_t)(bhv_desc_t *, int, struct cred *);
|
||||
typedef int (*vfs_mntupdate_t)(bhv_desc_t *, int *,
|
||||
struct xfs_mount_args *);
|
||||
typedef int (*vfs_root_t)(bhv_desc_t *, struct bhv_vnode **);
|
||||
typedef int (*vfs_statvfs_t)(bhv_desc_t *, bhv_statvfs_t *,
|
||||
struct bhv_vnode *);
|
||||
typedef int (*vfs_sync_t)(bhv_desc_t *, int, struct cred *);
|
||||
typedef int (*vfs_vget_t)(bhv_desc_t *, struct bhv_vnode **, struct fid *);
|
||||
typedef int (*vfs_dmapiops_t)(bhv_desc_t *, caddr_t);
|
||||
typedef int (*vfs_quotactl_t)(bhv_desc_t *, int, int, caddr_t);
|
||||
typedef void (*vfs_init_vnode_t)(bhv_desc_t *,
|
||||
struct bhv_vnode *, bhv_desc_t *, int);
|
||||
typedef void (*vfs_force_shutdown_t)(bhv_desc_t *, int, char *, int);
|
||||
typedef void (*vfs_freeze_t)(bhv_desc_t *);
|
||||
|
||||
typedef struct bhv_vfsops {
|
||||
bhv_position_t vf_position; /* behavior chain position */
|
||||
vfs_mount_t vfs_mount; /* mount file system */
|
||||
vfs_parseargs_t vfs_parseargs; /* parse mount options */
|
||||
vfs_showargs_t vfs_showargs; /* unparse mount options */
|
||||
vfs_unmount_t vfs_unmount; /* unmount file system */
|
||||
vfs_mntupdate_t vfs_mntupdate; /* update file system options */
|
||||
vfs_root_t vfs_root; /* get root vnode */
|
||||
vfs_statvfs_t vfs_statvfs; /* file system statistics */
|
||||
vfs_sync_t vfs_sync; /* flush files */
|
||||
vfs_vget_t vfs_vget; /* get vnode from fid */
|
||||
vfs_dmapiops_t vfs_dmapiops; /* data migration */
|
||||
vfs_quotactl_t vfs_quotactl; /* disk quota */
|
||||
vfs_init_vnode_t vfs_init_vnode; /* initialize a new vnode */
|
||||
vfs_force_shutdown_t vfs_force_shutdown; /* crash and burn */
|
||||
vfs_freeze_t vfs_freeze; /* freeze fs for snapshot */
|
||||
} bhv_vfsops_t;
|
||||
|
||||
/*
|
||||
* Virtual filesystem operations, operating from head bhv.
|
||||
*/
|
||||
#define VFSHEAD(v) ((v)->vfs_bh.bh_first)
|
||||
#define bhv_vfs_mount(v, ma,cr) vfs_mount(VFSHEAD(v), ma,cr)
|
||||
#define bhv_vfs_parseargs(v, o,ma,f) vfs_parseargs(VFSHEAD(v), o,ma,f)
|
||||
#define bhv_vfs_showargs(v, m) vfs_showargs(VFSHEAD(v), m)
|
||||
#define bhv_vfs_unmount(v, f,cr) vfs_unmount(VFSHEAD(v), f,cr)
|
||||
#define bhv_vfs_mntupdate(v, fl,args) vfs_mntupdate(VFSHEAD(v), fl,args)
|
||||
#define bhv_vfs_root(v, vpp) vfs_root(VFSHEAD(v), vpp)
|
||||
#define bhv_vfs_statvfs(v, sp,vp) vfs_statvfs(VFSHEAD(v), sp,vp)
|
||||
#define bhv_vfs_sync(v, flag,cr) vfs_sync(VFSHEAD(v), flag,cr)
|
||||
#define bhv_vfs_vget(v, vpp,fidp) vfs_vget(VFSHEAD(v), vpp,fidp)
|
||||
#define bhv_vfs_dmapiops(v, p) vfs_dmapiops(VFSHEAD(v), p)
|
||||
#define bhv_vfs_quotactl(v, c,id,p) vfs_quotactl(VFSHEAD(v), c,id,p)
|
||||
#define bhv_vfs_init_vnode(v, vp,b,ul) vfs_init_vnode(VFSHEAD(v), vp,b,ul)
|
||||
#define bhv_vfs_force_shutdown(v,u,f,l) vfs_force_shutdown(VFSHEAD(v), u,f,l)
|
||||
#define bhv_vfs_freeze(v) vfs_freeze(VFSHEAD(v))
|
||||
|
||||
/*
|
||||
* Virtual filesystem operations, operating from next bhv.
|
||||
*/
|
||||
#define bhv_next_vfs_mount(b, ma,cr) vfs_mount(b, ma,cr)
|
||||
#define bhv_next_vfs_parseargs(b, o,ma,f) vfs_parseargs(b, o,ma,f)
|
||||
#define bhv_next_vfs_showargs(b, m) vfs_showargs(b, m)
|
||||
#define bhv_next_vfs_unmount(b, f,cr) vfs_unmount(b, f,cr)
|
||||
#define bhv_next_vfs_mntupdate(b, fl,args) vfs_mntupdate(b, fl, args)
|
||||
#define bhv_next_vfs_root(b, vpp) vfs_root(b, vpp)
|
||||
#define bhv_next_vfs_statvfs(b, sp,vp) vfs_statvfs(b, sp,vp)
|
||||
#define bhv_next_vfs_sync(b, flag,cr) vfs_sync(b, flag,cr)
|
||||
#define bhv_next_vfs_vget(b, vpp,fidp) vfs_vget(b, vpp,fidp)
|
||||
#define bhv_next_vfs_dmapiops(b, p) vfs_dmapiops(b, p)
|
||||
#define bhv_next_vfs_quotactl(b, c,id,p) vfs_quotactl(b, c,id,p)
|
||||
#define bhv_next_vfs_init_vnode(b, vp,b2,ul) vfs_init_vnode(b, vp,b2,ul)
|
||||
#define bhv_next_force_shutdown(b, fl,f,l) vfs_force_shutdown(b, fl,f,l)
|
||||
#define bhv_next_vfs_freeze(b) vfs_freeze(b)
|
||||
|
||||
extern int vfs_mount(bhv_desc_t *, struct xfs_mount_args *, struct cred *);
|
||||
extern int vfs_parseargs(bhv_desc_t *, char *, struct xfs_mount_args *, int);
|
||||
extern int vfs_showargs(bhv_desc_t *, struct seq_file *);
|
||||
extern int vfs_unmount(bhv_desc_t *, int, struct cred *);
|
||||
extern int vfs_mntupdate(bhv_desc_t *, int *, struct xfs_mount_args *);
|
||||
extern int vfs_root(bhv_desc_t *, struct bhv_vnode **);
|
||||
extern int vfs_statvfs(bhv_desc_t *, bhv_statvfs_t *, struct bhv_vnode *);
|
||||
extern int vfs_sync(bhv_desc_t *, int, struct cred *);
|
||||
extern int vfs_vget(bhv_desc_t *, struct bhv_vnode **, struct fid *);
|
||||
extern int vfs_dmapiops(bhv_desc_t *, caddr_t);
|
||||
extern int vfs_quotactl(bhv_desc_t *, int, int, caddr_t);
|
||||
extern void vfs_init_vnode(bhv_desc_t *, struct bhv_vnode *, bhv_desc_t *, int);
|
||||
extern void vfs_force_shutdown(bhv_desc_t *, int, char *, int);
|
||||
extern void vfs_freeze(bhv_desc_t *);
|
||||
|
||||
#define vfs_test_for_freeze(vfs) ((vfs)->vfs_super->s_frozen)
|
||||
#define vfs_wait_for_freeze(vfs,l) vfs_check_frozen((vfs)->vfs_super, (l))
|
||||
|
||||
typedef struct bhv_module_vfsops {
|
||||
struct bhv_vfsops bhv_common;
|
||||
void * bhv_custom;
|
||||
} bhv_module_vfsops_t;
|
||||
|
||||
#define vfs_bhv_lookup(v, id) (bhv_lookup_range(&(v)->vfs_bh, (id), (id)))
|
||||
#define vfs_bhv_custom(b) (((bhv_module_vfsops_t*)BHV_OPS(b))->bhv_custom)
|
||||
#define vfs_bhv_set_custom(b,o) ((b)->bhv_custom = (void *)(o))
|
||||
#define vfs_bhv_clr_custom(b) ((b)->bhv_custom = NULL)
|
||||
|
||||
extern bhv_vfs_t *vfs_allocate(struct super_block *);
|
||||
extern bhv_vfs_t *vfs_from_sb(struct super_block *);
|
||||
extern void vfs_deallocate(bhv_vfs_t *);
|
||||
extern void vfs_insertbhv(bhv_vfs_t *, bhv_desc_t *, bhv_vfsops_t *, void *);
|
||||
|
||||
extern void vfs_insertops(bhv_vfs_t *, bhv_module_vfsops_t *);
|
||||
|
||||
extern void bhv_insert_all_vfsops(struct bhv_vfs *);
|
||||
extern void bhv_remove_all_vfsops(struct bhv_vfs *, int);
|
||||
extern void bhv_remove_vfsops(struct bhv_vfs *, int);
|
||||
#define xfs_test_for_freeze(mp) ((mp)->m_super->s_frozen)
|
||||
#define xfs_wait_for_freeze(mp,l) vfs_check_frozen((mp)->m_super, (l))
|
||||
|
||||
#endif /* __XFS_VFS_H__ */
|
||||
|
|
|
@ -16,9 +16,21 @@
|
|||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
#include "xfs.h"
|
||||
#include "xfs_vnodeops.h"
|
||||
#include "xfs_bmap_btree.h"
|
||||
#include "xfs_inode.h"
|
||||
|
||||
/*
|
||||
* And this gunk is needed for xfs_mount.h"
|
||||
*/
|
||||
#include "xfs_log.h"
|
||||
#include "xfs_trans.h"
|
||||
#include "xfs_sb.h"
|
||||
#include "xfs_dmapi.h"
|
||||
#include "xfs_inum.h"
|
||||
#include "xfs_ag.h"
|
||||
#include "xfs_mount.h"
|
||||
|
||||
uint64_t vn_generation; /* vnode generation number */
|
||||
DEFINE_SPINLOCK(vnumber_lock);
|
||||
|
||||
/*
|
||||
* Dedicated vnode inactive/reclaim sync semaphores.
|
||||
|
@ -39,19 +51,19 @@ vn_init(void)
|
|||
|
||||
void
|
||||
vn_iowait(
|
||||
bhv_vnode_t *vp)
|
||||
xfs_inode_t *ip)
|
||||
{
|
||||
wait_queue_head_t *wq = vptosync(vp);
|
||||
wait_queue_head_t *wq = vptosync(ip);
|
||||
|
||||
wait_event(*wq, (atomic_read(&vp->v_iocount) == 0));
|
||||
wait_event(*wq, (atomic_read(&ip->i_iocount) == 0));
|
||||
}
|
||||
|
||||
void
|
||||
vn_iowake(
|
||||
bhv_vnode_t *vp)
|
||||
xfs_inode_t *ip)
|
||||
{
|
||||
if (atomic_dec_and_test(&vp->v_iocount))
|
||||
wake_up(vptosync(vp));
|
||||
if (atomic_dec_and_test(&ip->i_iocount))
|
||||
wake_up(vptosync(ip));
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -61,13 +73,13 @@ vn_iowake(
|
|||
*/
|
||||
void
|
||||
vn_ioerror(
|
||||
bhv_vnode_t *vp,
|
||||
xfs_inode_t *ip,
|
||||
int error,
|
||||
char *f,
|
||||
int l)
|
||||
{
|
||||
if (unlikely(error == -ENODEV))
|
||||
bhv_vfs_force_shutdown(vp->v_vfsp, SHUTDOWN_DEVICE_REQ, f, l);
|
||||
xfs_do_force_shutdown(ip->i_mount, SHUTDOWN_DEVICE_REQ, f, l);
|
||||
}
|
||||
|
||||
bhv_vnode_t *
|
||||
|
@ -79,27 +91,8 @@ vn_initialize(
|
|||
XFS_STATS_INC(vn_active);
|
||||
XFS_STATS_INC(vn_alloc);
|
||||
|
||||
vp->v_flag = VMODIFIED;
|
||||
spinlock_init(&vp->v_lock, "v_lock");
|
||||
|
||||
spin_lock(&vnumber_lock);
|
||||
if (!++vn_generation) /* v_number shouldn't be zero */
|
||||
vn_generation++;
|
||||
vp->v_number = vn_generation;
|
||||
spin_unlock(&vnumber_lock);
|
||||
|
||||
ASSERT(VN_CACHED(vp) == 0);
|
||||
|
||||
/* Initialize the first behavior and the behavior chain head. */
|
||||
vn_bhv_head_init(VN_BHV_HEAD(vp), "vnode");
|
||||
|
||||
atomic_set(&vp->v_iocount, 0);
|
||||
|
||||
#ifdef XFS_VNODE_TRACE
|
||||
vp->v_trace = ktrace_alloc(VNODE_TRACE_SIZE, KM_SLEEP);
|
||||
#endif /* XFS_VNODE_TRACE */
|
||||
|
||||
vn_trace_exit(vp, __FUNCTION__, (inst_t *)__return_address);
|
||||
return vp;
|
||||
}
|
||||
|
||||
|
@ -150,12 +143,12 @@ __vn_revalidate(
|
|||
{
|
||||
int error;
|
||||
|
||||
vn_trace_entry(vp, __FUNCTION__, (inst_t *)__return_address);
|
||||
vn_trace_entry(xfs_vtoi(vp), __FUNCTION__, (inst_t *)__return_address);
|
||||
vattr->va_mask = XFS_AT_STAT | XFS_AT_XFLAGS;
|
||||
error = bhv_vop_getattr(vp, vattr, 0, NULL);
|
||||
error = xfs_getattr(xfs_vtoi(vp), vattr, 0);
|
||||
if (likely(!error)) {
|
||||
vn_revalidate_core(vp, vattr);
|
||||
VUNMODIFY(vp);
|
||||
xfs_iflags_clear(xfs_vtoi(vp), XFS_IMODIFIED);
|
||||
}
|
||||
return -error;
|
||||
}
|
||||
|
@ -180,24 +173,35 @@ vn_hold(
|
|||
|
||||
XFS_STATS_INC(vn_hold);
|
||||
|
||||
VN_LOCK(vp);
|
||||
inode = igrab(vn_to_inode(vp));
|
||||
ASSERT(inode);
|
||||
VN_UNLOCK(vp, 0);
|
||||
|
||||
return vp;
|
||||
}
|
||||
|
||||
#ifdef XFS_VNODE_TRACE
|
||||
|
||||
#define KTRACE_ENTER(vp, vk, s, line, ra) \
|
||||
ktrace_enter( (vp)->v_trace, \
|
||||
/*
|
||||
* Reference count of Linux inode if present, -1 if the xfs_inode
|
||||
* has no associated Linux inode.
|
||||
*/
|
||||
static inline int xfs_icount(struct xfs_inode *ip)
|
||||
{
|
||||
bhv_vnode_t *vp = XFS_ITOV_NULL(ip);
|
||||
|
||||
if (vp)
|
||||
return vn_count(vp);
|
||||
return -1;
|
||||
}
|
||||
|
||||
#define KTRACE_ENTER(ip, vk, s, line, ra) \
|
||||
ktrace_enter( (ip)->i_trace, \
|
||||
/* 0 */ (void *)(__psint_t)(vk), \
|
||||
/* 1 */ (void *)(s), \
|
||||
/* 2 */ (void *)(__psint_t) line, \
|
||||
/* 3 */ (void *)(__psint_t)(vn_count(vp)), \
|
||||
/* 3 */ (void *)(__psint_t)xfs_icount(ip), \
|
||||
/* 4 */ (void *)(ra), \
|
||||
/* 5 */ (void *)(__psunsigned_t)(vp)->v_flag, \
|
||||
/* 5 */ NULL, \
|
||||
/* 6 */ (void *)(__psint_t)current_cpu(), \
|
||||
/* 7 */ (void *)(__psint_t)current_pid(), \
|
||||
/* 8 */ (void *)__return_address, \
|
||||
|
@ -207,32 +211,32 @@ vn_hold(
|
|||
* Vnode tracing code.
|
||||
*/
|
||||
void
|
||||
vn_trace_entry(bhv_vnode_t *vp, const char *func, inst_t *ra)
|
||||
vn_trace_entry(xfs_inode_t *ip, const char *func, inst_t *ra)
|
||||
{
|
||||
KTRACE_ENTER(vp, VNODE_KTRACE_ENTRY, func, 0, ra);
|
||||
KTRACE_ENTER(ip, VNODE_KTRACE_ENTRY, func, 0, ra);
|
||||
}
|
||||
|
||||
void
|
||||
vn_trace_exit(bhv_vnode_t *vp, const char *func, inst_t *ra)
|
||||
vn_trace_exit(xfs_inode_t *ip, const char *func, inst_t *ra)
|
||||
{
|
||||
KTRACE_ENTER(vp, VNODE_KTRACE_EXIT, func, 0, ra);
|
||||
KTRACE_ENTER(ip, VNODE_KTRACE_EXIT, func, 0, ra);
|
||||
}
|
||||
|
||||
void
|
||||
vn_trace_hold(bhv_vnode_t *vp, char *file, int line, inst_t *ra)
|
||||
vn_trace_hold(xfs_inode_t *ip, char *file, int line, inst_t *ra)
|
||||
{
|
||||
KTRACE_ENTER(vp, VNODE_KTRACE_HOLD, file, line, ra);
|
||||
KTRACE_ENTER(ip, VNODE_KTRACE_HOLD, file, line, ra);
|
||||
}
|
||||
|
||||
void
|
||||
vn_trace_ref(bhv_vnode_t *vp, char *file, int line, inst_t *ra)
|
||||
vn_trace_ref(xfs_inode_t *ip, char *file, int line, inst_t *ra)
|
||||
{
|
||||
KTRACE_ENTER(vp, VNODE_KTRACE_REF, file, line, ra);
|
||||
KTRACE_ENTER(ip, VNODE_KTRACE_REF, file, line, ra);
|
||||
}
|
||||
|
||||
void
|
||||
vn_trace_rele(bhv_vnode_t *vp, char *file, int line, inst_t *ra)
|
||||
vn_trace_rele(xfs_inode_t *ip, char *file, int line, inst_t *ra)
|
||||
{
|
||||
KTRACE_ENTER(vp, VNODE_KTRACE_RELE, file, line, ra);
|
||||
KTRACE_ENTER(ip, VNODE_KTRACE_RELE, file, line, ra);
|
||||
}
|
||||
#endif /* XFS_VNODE_TRACE */
|
||||
|
|
|
@ -18,84 +18,31 @@
|
|||
#ifndef __XFS_VNODE_H__
|
||||
#define __XFS_VNODE_H__
|
||||
|
||||
struct uio;
|
||||
struct file;
|
||||
struct bhv_vfs;
|
||||
struct bhv_vattr;
|
||||
struct xfs_iomap;
|
||||
struct attrlist_cursor_kern;
|
||||
|
||||
typedef struct dentry bhv_vname_t;
|
||||
typedef __u64 bhv_vnumber_t;
|
||||
typedef struct inode bhv_vnode_t;
|
||||
|
||||
typedef enum bhv_vflags {
|
||||
VMODIFIED = 0x08, /* XFS inode state possibly differs */
|
||||
/* to the Linux inode state. */
|
||||
VTRUNCATED = 0x40, /* truncated down so flush-on-close */
|
||||
} bhv_vflags_t;
|
||||
|
||||
/*
|
||||
* MP locking protocols:
|
||||
* v_flag, v_vfsp VN_LOCK/VN_UNLOCK
|
||||
*/
|
||||
typedef struct bhv_vnode {
|
||||
bhv_vflags_t v_flag; /* vnode flags (see above) */
|
||||
bhv_vfs_t *v_vfsp; /* ptr to containing VFS */
|
||||
bhv_vnumber_t v_number; /* in-core vnode number */
|
||||
bhv_head_t v_bh; /* behavior head */
|
||||
spinlock_t v_lock; /* VN_LOCK/VN_UNLOCK */
|
||||
atomic_t v_iocount; /* outstanding I/O count */
|
||||
#ifdef XFS_VNODE_TRACE
|
||||
struct ktrace *v_trace; /* trace header structure */
|
||||
#endif
|
||||
struct inode v_inode; /* Linux inode */
|
||||
/* inode MUST be last */
|
||||
} bhv_vnode_t;
|
||||
|
||||
#define VN_ISLNK(vp) S_ISLNK((vp)->v_inode.i_mode)
|
||||
#define VN_ISREG(vp) S_ISREG((vp)->v_inode.i_mode)
|
||||
#define VN_ISDIR(vp) S_ISDIR((vp)->v_inode.i_mode)
|
||||
#define VN_ISCHR(vp) S_ISCHR((vp)->v_inode.i_mode)
|
||||
#define VN_ISBLK(vp) S_ISBLK((vp)->v_inode.i_mode)
|
||||
|
||||
#define VNODE_POSITION_BASE BHV_POSITION_BASE /* chain bottom */
|
||||
#define VNODE_POSITION_TOP BHV_POSITION_TOP /* chain top */
|
||||
#define VNODE_POSITION_INVALID BHV_POSITION_INVALID /* invalid pos. num */
|
||||
|
||||
typedef enum {
|
||||
VN_BHV_UNKNOWN, /* not specified */
|
||||
VN_BHV_XFS, /* xfs */
|
||||
VN_BHV_DM, /* data migration */
|
||||
VN_BHV_QM, /* quota manager */
|
||||
VN_BHV_IO, /* IO path */
|
||||
VN_BHV_END /* housekeeping end-of-range */
|
||||
} vn_bhv_t;
|
||||
|
||||
#define VNODE_POSITION_XFS (VNODE_POSITION_BASE)
|
||||
#define VNODE_POSITION_DM (VNODE_POSITION_BASE+10)
|
||||
#define VNODE_POSITION_QM (VNODE_POSITION_BASE+20)
|
||||
#define VNODE_POSITION_IO (VNODE_POSITION_BASE+30)
|
||||
|
||||
/*
|
||||
* Macros for dealing with the behavior descriptor inside of the vnode.
|
||||
*/
|
||||
#define BHV_TO_VNODE(bdp) ((bhv_vnode_t *)BHV_VOBJ(bdp))
|
||||
#define BHV_TO_VNODE_NULL(bdp) ((bhv_vnode_t *)BHV_VOBJNULL(bdp))
|
||||
|
||||
#define VN_BHV_HEAD(vp) ((bhv_head_t *)(&((vp)->v_bh)))
|
||||
#define vn_bhv_head_init(bhp,name) bhv_head_init(bhp,name)
|
||||
#define vn_bhv_remove(bhp,bdp) bhv_remove(bhp,bdp)
|
||||
#define VN_ISLNK(vp) S_ISLNK((vp)->i_mode)
|
||||
#define VN_ISREG(vp) S_ISREG((vp)->i_mode)
|
||||
#define VN_ISDIR(vp) S_ISDIR((vp)->i_mode)
|
||||
#define VN_ISCHR(vp) S_ISCHR((vp)->i_mode)
|
||||
#define VN_ISBLK(vp) S_ISBLK((vp)->i_mode)
|
||||
|
||||
/*
|
||||
* Vnode to Linux inode mapping.
|
||||
*/
|
||||
static inline struct bhv_vnode *vn_from_inode(struct inode *inode)
|
||||
static inline bhv_vnode_t *vn_from_inode(struct inode *inode)
|
||||
{
|
||||
return container_of(inode, bhv_vnode_t, v_inode);
|
||||
return inode;
|
||||
}
|
||||
static inline struct inode *vn_to_inode(struct bhv_vnode *vnode)
|
||||
static inline struct inode *vn_to_inode(bhv_vnode_t *vnode)
|
||||
{
|
||||
return &vnode->v_inode;
|
||||
return vnode;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -111,200 +58,13 @@ typedef enum bhv_vrwlock {
|
|||
} bhv_vrwlock_t;
|
||||
|
||||
/*
|
||||
* Return values for bhv_vop_inactive. A return value of
|
||||
* Return values for xfs_inactive. A return value of
|
||||
* VN_INACTIVE_NOCACHE implies that the file system behavior
|
||||
* has disassociated its state and bhv_desc_t from the vnode.
|
||||
*/
|
||||
#define VN_INACTIVE_CACHE 0
|
||||
#define VN_INACTIVE_NOCACHE 1
|
||||
|
||||
/*
|
||||
* Values for the cmd code given to vop_vnode_change.
|
||||
*/
|
||||
typedef enum bhv_vchange {
|
||||
VCHANGE_FLAGS_FRLOCKS = 0,
|
||||
VCHANGE_FLAGS_ENF_LOCKING = 1,
|
||||
VCHANGE_FLAGS_TRUNCATED = 2,
|
||||
VCHANGE_FLAGS_PAGE_DIRTY = 3,
|
||||
VCHANGE_FLAGS_IOEXCL_COUNT = 4
|
||||
} bhv_vchange_t;
|
||||
|
||||
typedef int (*vop_open_t)(bhv_desc_t *, struct cred *);
|
||||
typedef ssize_t (*vop_read_t)(bhv_desc_t *, struct kiocb *,
|
||||
const struct iovec *, unsigned int,
|
||||
loff_t *, int, struct cred *);
|
||||
typedef ssize_t (*vop_write_t)(bhv_desc_t *, struct kiocb *,
|
||||
const struct iovec *, unsigned int,
|
||||
loff_t *, int, struct cred *);
|
||||
typedef ssize_t (*vop_splice_read_t)(bhv_desc_t *, struct file *, loff_t *,
|
||||
struct pipe_inode_info *, size_t, int, int,
|
||||
struct cred *);
|
||||
typedef ssize_t (*vop_splice_write_t)(bhv_desc_t *, struct pipe_inode_info *,
|
||||
struct file *, loff_t *, size_t, int, int,
|
||||
struct cred *);
|
||||
typedef int (*vop_ioctl_t)(bhv_desc_t *, struct inode *, struct file *,
|
||||
int, unsigned int, void __user *);
|
||||
typedef int (*vop_getattr_t)(bhv_desc_t *, struct bhv_vattr *, int,
|
||||
struct cred *);
|
||||
typedef int (*vop_setattr_t)(bhv_desc_t *, struct bhv_vattr *, int,
|
||||
struct cred *);
|
||||
typedef int (*vop_access_t)(bhv_desc_t *, int, struct cred *);
|
||||
typedef int (*vop_lookup_t)(bhv_desc_t *, bhv_vname_t *, bhv_vnode_t **,
|
||||
int, bhv_vnode_t *, struct cred *);
|
||||
typedef int (*vop_create_t)(bhv_desc_t *, bhv_vname_t *, struct bhv_vattr *,
|
||||
bhv_vnode_t **, struct cred *);
|
||||
typedef int (*vop_remove_t)(bhv_desc_t *, bhv_vname_t *, struct cred *);
|
||||
typedef int (*vop_link_t)(bhv_desc_t *, bhv_vnode_t *, bhv_vname_t *,
|
||||
struct cred *);
|
||||
typedef int (*vop_rename_t)(bhv_desc_t *, bhv_vname_t *, bhv_vnode_t *,
|
||||
bhv_vname_t *, struct cred *);
|
||||
typedef int (*vop_mkdir_t)(bhv_desc_t *, bhv_vname_t *, struct bhv_vattr *,
|
||||
bhv_vnode_t **, struct cred *);
|
||||
typedef int (*vop_rmdir_t)(bhv_desc_t *, bhv_vname_t *, struct cred *);
|
||||
typedef int (*vop_readdir_t)(bhv_desc_t *, struct uio *, struct cred *,
|
||||
int *);
|
||||
typedef int (*vop_symlink_t)(bhv_desc_t *, bhv_vname_t *, struct bhv_vattr*,
|
||||
char *, bhv_vnode_t **, struct cred *);
|
||||
typedef int (*vop_readlink_t)(bhv_desc_t *, struct uio *, int,
|
||||
struct cred *);
|
||||
typedef int (*vop_fsync_t)(bhv_desc_t *, int, struct cred *,
|
||||
xfs_off_t, xfs_off_t);
|
||||
typedef int (*vop_inactive_t)(bhv_desc_t *, struct cred *);
|
||||
typedef int (*vop_fid2_t)(bhv_desc_t *, struct fid *);
|
||||
typedef int (*vop_release_t)(bhv_desc_t *);
|
||||
typedef int (*vop_rwlock_t)(bhv_desc_t *, bhv_vrwlock_t);
|
||||
typedef void (*vop_rwunlock_t)(bhv_desc_t *, bhv_vrwlock_t);
|
||||
typedef int (*vop_bmap_t)(bhv_desc_t *, xfs_off_t, ssize_t, int,
|
||||
struct xfs_iomap *, int *);
|
||||
typedef int (*vop_reclaim_t)(bhv_desc_t *);
|
||||
typedef int (*vop_attr_get_t)(bhv_desc_t *, const char *, char *, int *,
|
||||
int, struct cred *);
|
||||
typedef int (*vop_attr_set_t)(bhv_desc_t *, const char *, char *, int,
|
||||
int, struct cred *);
|
||||
typedef int (*vop_attr_remove_t)(bhv_desc_t *, const char *,
|
||||
int, struct cred *);
|
||||
typedef int (*vop_attr_list_t)(bhv_desc_t *, char *, int, int,
|
||||
struct attrlist_cursor_kern *, struct cred *);
|
||||
typedef void (*vop_link_removed_t)(bhv_desc_t *, bhv_vnode_t *, int);
|
||||
typedef void (*vop_vnode_change_t)(bhv_desc_t *, bhv_vchange_t, __psint_t);
|
||||
typedef void (*vop_ptossvp_t)(bhv_desc_t *, xfs_off_t, xfs_off_t, int);
|
||||
typedef int (*vop_pflushinvalvp_t)(bhv_desc_t *, xfs_off_t, xfs_off_t, int);
|
||||
typedef int (*vop_pflushvp_t)(bhv_desc_t *, xfs_off_t, xfs_off_t,
|
||||
uint64_t, int);
|
||||
typedef int (*vop_iflush_t)(bhv_desc_t *, int);
|
||||
|
||||
|
||||
typedef struct bhv_vnodeops {
|
||||
bhv_position_t vn_position; /* position within behavior chain */
|
||||
vop_open_t vop_open;
|
||||
vop_read_t vop_read;
|
||||
vop_write_t vop_write;
|
||||
vop_splice_read_t vop_splice_read;
|
||||
vop_splice_write_t vop_splice_write;
|
||||
vop_ioctl_t vop_ioctl;
|
||||
vop_getattr_t vop_getattr;
|
||||
vop_setattr_t vop_setattr;
|
||||
vop_access_t vop_access;
|
||||
vop_lookup_t vop_lookup;
|
||||
vop_create_t vop_create;
|
||||
vop_remove_t vop_remove;
|
||||
vop_link_t vop_link;
|
||||
vop_rename_t vop_rename;
|
||||
vop_mkdir_t vop_mkdir;
|
||||
vop_rmdir_t vop_rmdir;
|
||||
vop_readdir_t vop_readdir;
|
||||
vop_symlink_t vop_symlink;
|
||||
vop_readlink_t vop_readlink;
|
||||
vop_fsync_t vop_fsync;
|
||||
vop_inactive_t vop_inactive;
|
||||
vop_fid2_t vop_fid2;
|
||||
vop_rwlock_t vop_rwlock;
|
||||
vop_rwunlock_t vop_rwunlock;
|
||||
vop_bmap_t vop_bmap;
|
||||
vop_reclaim_t vop_reclaim;
|
||||
vop_attr_get_t vop_attr_get;
|
||||
vop_attr_set_t vop_attr_set;
|
||||
vop_attr_remove_t vop_attr_remove;
|
||||
vop_attr_list_t vop_attr_list;
|
||||
vop_link_removed_t vop_link_removed;
|
||||
vop_vnode_change_t vop_vnode_change;
|
||||
vop_ptossvp_t vop_tosspages;
|
||||
vop_pflushinvalvp_t vop_flushinval_pages;
|
||||
vop_pflushvp_t vop_flush_pages;
|
||||
vop_release_t vop_release;
|
||||
vop_iflush_t vop_iflush;
|
||||
} bhv_vnodeops_t;
|
||||
|
||||
/*
|
||||
* Virtual node operations, operating from head bhv.
|
||||
*/
|
||||
#define VNHEAD(vp) ((vp)->v_bh.bh_first)
|
||||
#define VOP(op, vp) (*((bhv_vnodeops_t *)VNHEAD(vp)->bd_ops)->op)
|
||||
#define bhv_vop_open(vp, cr) VOP(vop_open, vp)(VNHEAD(vp),cr)
|
||||
#define bhv_vop_read(vp,file,iov,segs,offset,ioflags,cr) \
|
||||
VOP(vop_read, vp)(VNHEAD(vp),file,iov,segs,offset,ioflags,cr)
|
||||
#define bhv_vop_write(vp,file,iov,segs,offset,ioflags,cr) \
|
||||
VOP(vop_write, vp)(VNHEAD(vp),file,iov,segs,offset,ioflags,cr)
|
||||
#define bhv_vop_splice_read(vp,f,o,pipe,cnt,fl,iofl,cr) \
|
||||
VOP(vop_splice_read, vp)(VNHEAD(vp),f,o,pipe,cnt,fl,iofl,cr)
|
||||
#define bhv_vop_splice_write(vp,f,o,pipe,cnt,fl,iofl,cr) \
|
||||
VOP(vop_splice_write, vp)(VNHEAD(vp),f,o,pipe,cnt,fl,iofl,cr)
|
||||
#define bhv_vop_bmap(vp,of,sz,rw,b,n) \
|
||||
VOP(vop_bmap, vp)(VNHEAD(vp),of,sz,rw,b,n)
|
||||
#define bhv_vop_getattr(vp, vap,f,cr) \
|
||||
VOP(vop_getattr, vp)(VNHEAD(vp), vap,f,cr)
|
||||
#define bhv_vop_setattr(vp, vap,f,cr) \
|
||||
VOP(vop_setattr, vp)(VNHEAD(vp), vap,f,cr)
|
||||
#define bhv_vop_access(vp, mode,cr) VOP(vop_access, vp)(VNHEAD(vp), mode,cr)
|
||||
#define bhv_vop_lookup(vp,d,vpp,f,rdir,cr) \
|
||||
VOP(vop_lookup, vp)(VNHEAD(vp),d,vpp,f,rdir,cr)
|
||||
#define bhv_vop_create(dvp,d,vap,vpp,cr) \
|
||||
VOP(vop_create, dvp)(VNHEAD(dvp),d,vap,vpp,cr)
|
||||
#define bhv_vop_remove(dvp,d,cr) VOP(vop_remove, dvp)(VNHEAD(dvp),d,cr)
|
||||
#define bhv_vop_link(dvp,fvp,d,cr) VOP(vop_link, dvp)(VNHEAD(dvp),fvp,d,cr)
|
||||
#define bhv_vop_rename(fvp,fnm,tdvp,tnm,cr) \
|
||||
VOP(vop_rename, fvp)(VNHEAD(fvp),fnm,tdvp,tnm,cr)
|
||||
#define bhv_vop_mkdir(dp,d,vap,vpp,cr) \
|
||||
VOP(vop_mkdir, dp)(VNHEAD(dp),d,vap,vpp,cr)
|
||||
#define bhv_vop_rmdir(dp,d,cr) VOP(vop_rmdir, dp)(VNHEAD(dp),d,cr)
|
||||
#define bhv_vop_readdir(vp,uiop,cr,eofp) \
|
||||
VOP(vop_readdir, vp)(VNHEAD(vp),uiop,cr,eofp)
|
||||
#define bhv_vop_symlink(dvp,d,vap,tnm,vpp,cr) \
|
||||
VOP(vop_symlink, dvp)(VNHEAD(dvp),d,vap,tnm,vpp,cr)
|
||||
#define bhv_vop_readlink(vp,uiop,fl,cr) \
|
||||
VOP(vop_readlink, vp)(VNHEAD(vp),uiop,fl,cr)
|
||||
#define bhv_vop_fsync(vp,f,cr,b,e) VOP(vop_fsync, vp)(VNHEAD(vp),f,cr,b,e)
|
||||
#define bhv_vop_inactive(vp,cr) VOP(vop_inactive, vp)(VNHEAD(vp),cr)
|
||||
#define bhv_vop_release(vp) VOP(vop_release, vp)(VNHEAD(vp))
|
||||
#define bhv_vop_fid2(vp,fidp) VOP(vop_fid2, vp)(VNHEAD(vp),fidp)
|
||||
#define bhv_vop_rwlock(vp,i) VOP(vop_rwlock, vp)(VNHEAD(vp),i)
|
||||
#define bhv_vop_rwlock_try(vp,i) VOP(vop_rwlock, vp)(VNHEAD(vp),i)
|
||||
#define bhv_vop_rwunlock(vp,i) VOP(vop_rwunlock, vp)(VNHEAD(vp),i)
|
||||
#define bhv_vop_frlock(vp,c,fl,flags,offset,fr) \
|
||||
VOP(vop_frlock, vp)(VNHEAD(vp),c,fl,flags,offset,fr)
|
||||
#define bhv_vop_reclaim(vp) VOP(vop_reclaim, vp)(VNHEAD(vp))
|
||||
#define bhv_vop_attr_get(vp, name, val, vallenp, fl, cred) \
|
||||
VOP(vop_attr_get, vp)(VNHEAD(vp),name,val,vallenp,fl,cred)
|
||||
#define bhv_vop_attr_set(vp, name, val, vallen, fl, cred) \
|
||||
VOP(vop_attr_set, vp)(VNHEAD(vp),name,val,vallen,fl,cred)
|
||||
#define bhv_vop_attr_remove(vp, name, flags, cred) \
|
||||
VOP(vop_attr_remove, vp)(VNHEAD(vp),name,flags,cred)
|
||||
#define bhv_vop_attr_list(vp, buf, buflen, fl, cursor, cred) \
|
||||
VOP(vop_attr_list, vp)(VNHEAD(vp),buf,buflen,fl,cursor,cred)
|
||||
#define bhv_vop_link_removed(vp, dvp, linkzero) \
|
||||
VOP(vop_link_removed, vp)(VNHEAD(vp), dvp, linkzero)
|
||||
#define bhv_vop_vnode_change(vp, cmd, val) \
|
||||
VOP(vop_vnode_change, vp)(VNHEAD(vp), cmd, val)
|
||||
#define bhv_vop_toss_pages(vp, first, last, fiopt) \
|
||||
VOP(vop_tosspages, vp)(VNHEAD(vp), first, last, fiopt)
|
||||
#define bhv_vop_flushinval_pages(vp, first, last, fiopt) \
|
||||
VOP(vop_flushinval_pages, vp)(VNHEAD(vp),first,last,fiopt)
|
||||
#define bhv_vop_flush_pages(vp, first, last, flags, fiopt) \
|
||||
VOP(vop_flush_pages, vp)(VNHEAD(vp),first,last,flags,fiopt)
|
||||
#define bhv_vop_ioctl(vp, inode, filp, fl, cmd, arg) \
|
||||
VOP(vop_ioctl, vp)(VNHEAD(vp),inode,filp,fl,cmd,arg)
|
||||
#define bhv_vop_iflush(vp, flags) VOP(vop_iflush, vp)(VNHEAD(vp), flags)
|
||||
|
||||
/*
|
||||
* Flags for read/write calls - same values as IRIX
|
||||
*/
|
||||
|
@ -428,16 +188,19 @@ typedef struct bhv_vattr {
|
|||
|
||||
extern void vn_init(void);
|
||||
extern bhv_vnode_t *vn_initialize(struct inode *);
|
||||
extern int vn_revalidate(struct bhv_vnode *);
|
||||
extern int __vn_revalidate(struct bhv_vnode *, bhv_vattr_t *);
|
||||
extern void vn_revalidate_core(struct bhv_vnode *, bhv_vattr_t *);
|
||||
extern 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__ */
|
||||
|
|
|
@ -287,45 +287,6 @@ xfs_qm_rele_quotafs_ref(
|
|||
XFS_QM_UNLOCK(xfs_Gqm);
|
||||
}
|
||||
|
||||
/*
|
||||
* This is called at mount time from xfs_mountfs to initialize the quotainfo
|
||||
* structure and start the global quota manager (xfs_Gqm) if it hasn't done
|
||||
* so already. Note that the superblock has not been read in yet.
|
||||
*/
|
||||
void
|
||||
xfs_qm_mount_quotainit(
|
||||
xfs_mount_t *mp,
|
||||
uint flags)
|
||||
{
|
||||
/*
|
||||
* User, projects or group quotas has to be on.
|
||||
*/
|
||||
ASSERT(flags & (XFSMNT_UQUOTA | XFSMNT_PQUOTA | XFSMNT_GQUOTA));
|
||||
|
||||
/*
|
||||
* Initialize the flags in the mount structure. From this point
|
||||
* onwards we look at m_qflags to figure out if quotas's ON/OFF, etc.
|
||||
* Note that we enforce nothing if accounting is off.
|
||||
* ie. XFSMNT_*QUOTA must be ON for XFSMNT_*QUOTAENF.
|
||||
* It isn't necessary to take the quotaoff lock to do this; this is
|
||||
* called from mount.
|
||||
*/
|
||||
if (flags & XFSMNT_UQUOTA) {
|
||||
mp->m_qflags |= (XFS_UQUOTA_ACCT | XFS_UQUOTA_ACTIVE);
|
||||
if (flags & XFSMNT_UQUOTAENF)
|
||||
mp->m_qflags |= XFS_UQUOTA_ENFD;
|
||||
}
|
||||
if (flags & XFSMNT_GQUOTA) {
|
||||
mp->m_qflags |= (XFS_GQUOTA_ACCT | XFS_GQUOTA_ACTIVE);
|
||||
if (flags & XFSMNT_GQUOTAENF)
|
||||
mp->m_qflags |= XFS_OQUOTA_ENFD;
|
||||
} else if (flags & XFSMNT_PQUOTA) {
|
||||
mp->m_qflags |= (XFS_PQUOTA_ACCT | XFS_PQUOTA_ACTIVE);
|
||||
if (flags & XFSMNT_PQUOTAENF)
|
||||
mp->m_qflags |= XFS_OQUOTA_ENFD;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Just destroy the quotainfo structure.
|
||||
*/
|
||||
|
@ -1039,7 +1000,7 @@ xfs_qm_dqdetach(
|
|||
int
|
||||
xfs_qm_sync(
|
||||
xfs_mount_t *mp,
|
||||
short flags)
|
||||
int flags)
|
||||
{
|
||||
int recl, restarts;
|
||||
xfs_dquot_t *dqp;
|
||||
|
@ -1717,7 +1678,6 @@ xfs_qm_get_rtblks(
|
|||
xfs_extnum_t idx; /* extent record index */
|
||||
xfs_ifork_t *ifp; /* inode fork pointer */
|
||||
xfs_extnum_t nextents; /* number of extent entries */
|
||||
xfs_bmbt_rec_t *ep; /* pointer to an extent entry */
|
||||
int error;
|
||||
|
||||
ASSERT(XFS_IS_REALTIME_INODE(ip));
|
||||
|
@ -1728,10 +1688,8 @@ xfs_qm_get_rtblks(
|
|||
}
|
||||
rtblks = 0;
|
||||
nextents = ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t);
|
||||
for (idx = 0; idx < nextents; idx++) {
|
||||
ep = xfs_iext_get_ext(ifp, idx);
|
||||
rtblks += xfs_bmbt_get_blockcount(ep);
|
||||
}
|
||||
for (idx = 0; idx < nextents; idx++)
|
||||
rtblks += xfs_bmbt_get_blockcount(xfs_iext_get_ext(ifp, idx));
|
||||
*O_rtblks = (xfs_qcnt_t)rtblks;
|
||||
return 0;
|
||||
}
|
||||
|
@ -2459,8 +2417,7 @@ xfs_qm_vop_dqalloc(
|
|||
lockflags = XFS_ILOCK_EXCL;
|
||||
xfs_ilock(ip, lockflags);
|
||||
|
||||
if ((flags & XFS_QMOPT_INHERIT) &&
|
||||
XFS_INHERIT_GID(ip, XFS_MTOVFS(mp)))
|
||||
if ((flags & XFS_QMOPT_INHERIT) && XFS_INHERIT_GID(ip))
|
||||
gid = ip->i_d.di_gid;
|
||||
|
||||
/*
|
||||
|
|
|
@ -166,12 +166,11 @@ typedef struct xfs_dquot_acct {
|
|||
|
||||
extern void xfs_qm_destroy_quotainfo(xfs_mount_t *);
|
||||
extern int xfs_qm_mount_quotas(xfs_mount_t *, int);
|
||||
extern void xfs_qm_mount_quotainit(xfs_mount_t *, uint);
|
||||
extern int xfs_qm_quotacheck(xfs_mount_t *);
|
||||
extern void xfs_qm_unmount_quotadestroy(xfs_mount_t *);
|
||||
extern int xfs_qm_unmount_quotas(xfs_mount_t *);
|
||||
extern int xfs_qm_write_sb_changes(xfs_mount_t *, __int64_t);
|
||||
extern int xfs_qm_sync(xfs_mount_t *, short);
|
||||
extern int xfs_qm_sync(xfs_mount_t *, int);
|
||||
|
||||
/* dquot stuff */
|
||||
extern boolean_t xfs_qm_dqalloc_incore(xfs_dquot_t **);
|
||||
|
@ -199,7 +198,8 @@ extern void xfs_qm_freelist_unlink(xfs_dquot_t *);
|
|||
extern int xfs_qm_freelist_lock_nowait(xfs_qm_t *);
|
||||
|
||||
/* system call interface */
|
||||
extern int xfs_qm_quotactl(bhv_desc_t *, int, int, xfs_caddr_t);
|
||||
extern int xfs_qm_quotactl(struct xfs_mount *, int, int,
|
||||
xfs_caddr_t);
|
||||
|
||||
#ifdef DEBUG
|
||||
extern int xfs_qm_internalqcheck(xfs_mount_t *);
|
||||
|
|
|
@ -48,172 +48,13 @@
|
|||
#include "xfs_buf_item.h"
|
||||
#include "xfs_qm.h"
|
||||
|
||||
#define MNTOPT_QUOTA "quota" /* disk quotas (user) */
|
||||
#define MNTOPT_NOQUOTA "noquota" /* no quotas */
|
||||
#define MNTOPT_USRQUOTA "usrquota" /* user quota enabled */
|
||||
#define MNTOPT_GRPQUOTA "grpquota" /* group quota enabled */
|
||||
#define MNTOPT_PRJQUOTA "prjquota" /* project quota enabled */
|
||||
#define MNTOPT_UQUOTA "uquota" /* user quota (IRIX variant) */
|
||||
#define MNTOPT_GQUOTA "gquota" /* group quota (IRIX variant) */
|
||||
#define MNTOPT_PQUOTA "pquota" /* project quota (IRIX variant) */
|
||||
#define MNTOPT_UQUOTANOENF "uqnoenforce"/* user quota limit enforcement */
|
||||
#define MNTOPT_GQUOTANOENF "gqnoenforce"/* group quota limit enforcement */
|
||||
#define MNTOPT_PQUOTANOENF "pqnoenforce"/* project quota limit enforcement */
|
||||
#define MNTOPT_QUOTANOENF "qnoenforce" /* same as uqnoenforce */
|
||||
|
||||
STATIC int
|
||||
xfs_qm_parseargs(
|
||||
struct bhv_desc *bhv,
|
||||
char *options,
|
||||
struct xfs_mount_args *args,
|
||||
int update)
|
||||
{
|
||||
size_t length;
|
||||
char *local_options = options;
|
||||
char *this_char;
|
||||
int error;
|
||||
int referenced = update;
|
||||
|
||||
while ((this_char = strsep(&local_options, ",")) != NULL) {
|
||||
length = strlen(this_char);
|
||||
if (local_options)
|
||||
length++;
|
||||
|
||||
if (!strcmp(this_char, MNTOPT_NOQUOTA)) {
|
||||
args->flags &= ~(XFSMNT_UQUOTAENF|XFSMNT_UQUOTA);
|
||||
args->flags &= ~(XFSMNT_GQUOTAENF|XFSMNT_GQUOTA);
|
||||
referenced = update;
|
||||
} else if (!strcmp(this_char, MNTOPT_QUOTA) ||
|
||||
!strcmp(this_char, MNTOPT_UQUOTA) ||
|
||||
!strcmp(this_char, MNTOPT_USRQUOTA)) {
|
||||
args->flags |= XFSMNT_UQUOTA | XFSMNT_UQUOTAENF;
|
||||
referenced = 1;
|
||||
} else if (!strcmp(this_char, MNTOPT_QUOTANOENF) ||
|
||||
!strcmp(this_char, MNTOPT_UQUOTANOENF)) {
|
||||
args->flags |= XFSMNT_UQUOTA;
|
||||
args->flags &= ~XFSMNT_UQUOTAENF;
|
||||
referenced = 1;
|
||||
} else if (!strcmp(this_char, MNTOPT_PQUOTA) ||
|
||||
!strcmp(this_char, MNTOPT_PRJQUOTA)) {
|
||||
args->flags |= XFSMNT_PQUOTA | XFSMNT_PQUOTAENF;
|
||||
referenced = 1;
|
||||
} else if (!strcmp(this_char, MNTOPT_PQUOTANOENF)) {
|
||||
args->flags |= XFSMNT_PQUOTA;
|
||||
args->flags &= ~XFSMNT_PQUOTAENF;
|
||||
referenced = 1;
|
||||
} else if (!strcmp(this_char, MNTOPT_GQUOTA) ||
|
||||
!strcmp(this_char, MNTOPT_GRPQUOTA)) {
|
||||
args->flags |= XFSMNT_GQUOTA | XFSMNT_GQUOTAENF;
|
||||
referenced = 1;
|
||||
} else if (!strcmp(this_char, MNTOPT_GQUOTANOENF)) {
|
||||
args->flags |= XFSMNT_GQUOTA;
|
||||
args->flags &= ~XFSMNT_GQUOTAENF;
|
||||
referenced = 1;
|
||||
} else {
|
||||
if (local_options)
|
||||
*(local_options-1) = ',';
|
||||
continue;
|
||||
}
|
||||
|
||||
while (length--)
|
||||
*this_char++ = ',';
|
||||
}
|
||||
|
||||
if ((args->flags & XFSMNT_GQUOTA) && (args->flags & XFSMNT_PQUOTA)) {
|
||||
cmn_err(CE_WARN,
|
||||
"XFS: cannot mount with both project and group quota");
|
||||
return XFS_ERROR(EINVAL);
|
||||
}
|
||||
|
||||
error = bhv_next_vfs_parseargs(BHV_NEXT(bhv), options, args, update);
|
||||
if (!error && !referenced)
|
||||
bhv_remove_vfsops(bhvtovfs(bhv), VFS_POSITION_QM);
|
||||
return error;
|
||||
}
|
||||
|
||||
STATIC int
|
||||
xfs_qm_showargs(
|
||||
struct bhv_desc *bhv,
|
||||
struct seq_file *m)
|
||||
{
|
||||
struct bhv_vfs *vfsp = bhvtovfs(bhv);
|
||||
struct xfs_mount *mp = XFS_VFSTOM(vfsp);
|
||||
|
||||
if (mp->m_qflags & XFS_UQUOTA_ACCT) {
|
||||
(mp->m_qflags & XFS_UQUOTA_ENFD) ?
|
||||
seq_puts(m, "," MNTOPT_USRQUOTA) :
|
||||
seq_puts(m, "," MNTOPT_UQUOTANOENF);
|
||||
}
|
||||
|
||||
if (mp->m_qflags & XFS_PQUOTA_ACCT) {
|
||||
(mp->m_qflags & XFS_OQUOTA_ENFD) ?
|
||||
seq_puts(m, "," MNTOPT_PRJQUOTA) :
|
||||
seq_puts(m, "," MNTOPT_PQUOTANOENF);
|
||||
}
|
||||
|
||||
if (mp->m_qflags & XFS_GQUOTA_ACCT) {
|
||||
(mp->m_qflags & XFS_OQUOTA_ENFD) ?
|
||||
seq_puts(m, "," MNTOPT_GRPQUOTA) :
|
||||
seq_puts(m, "," MNTOPT_GQUOTANOENF);
|
||||
}
|
||||
|
||||
if (!(mp->m_qflags & XFS_ALL_QUOTA_ACCT))
|
||||
seq_puts(m, "," MNTOPT_NOQUOTA);
|
||||
|
||||
return bhv_next_vfs_showargs(BHV_NEXT(bhv), m);
|
||||
}
|
||||
|
||||
STATIC int
|
||||
xfs_qm_mount(
|
||||
struct bhv_desc *bhv,
|
||||
struct xfs_mount_args *args,
|
||||
struct cred *cr)
|
||||
{
|
||||
struct bhv_vfs *vfsp = bhvtovfs(bhv);
|
||||
struct xfs_mount *mp = XFS_VFSTOM(vfsp);
|
||||
|
||||
if (args->flags & (XFSMNT_UQUOTA | XFSMNT_GQUOTA | XFSMNT_PQUOTA))
|
||||
xfs_qm_mount_quotainit(mp, args->flags);
|
||||
return bhv_next_vfs_mount(BHV_NEXT(bhv), args, cr);
|
||||
}
|
||||
|
||||
/*
|
||||
* Directory tree accounting is implemented using project quotas, where
|
||||
* the project identifier is inherited from parent directories.
|
||||
* A statvfs (df, etc.) of a directory that is using project quota should
|
||||
* return a statvfs of the project, not the entire filesystem.
|
||||
* This makes such trees appear as if they are filesystems in themselves.
|
||||
*/
|
||||
STATIC int
|
||||
xfs_qm_statvfs(
|
||||
struct bhv_desc *bhv,
|
||||
STATIC void
|
||||
xfs_fill_statvfs_from_dquot(
|
||||
bhv_statvfs_t *statp,
|
||||
struct bhv_vnode *vnode)
|
||||
xfs_disk_dquot_t *dp)
|
||||
{
|
||||
xfs_mount_t *mp;
|
||||
xfs_inode_t *ip;
|
||||
xfs_dquot_t *dqp;
|
||||
xfs_disk_dquot_t *dp;
|
||||
__uint64_t limit;
|
||||
int error;
|
||||
|
||||
error = bhv_next_vfs_statvfs(BHV_NEXT(bhv), statp, vnode);
|
||||
if (error || !vnode)
|
||||
return error;
|
||||
|
||||
mp = xfs_vfstom(bhvtovfs(bhv));
|
||||
ip = xfs_vtoi(vnode);
|
||||
|
||||
if (!(ip->i_d.di_flags & XFS_DIFLAG_PROJINHERIT))
|
||||
return 0;
|
||||
if (!(mp->m_qflags & XFS_PQUOTA_ACCT))
|
||||
return 0;
|
||||
if (!(mp->m_qflags & XFS_OQUOTA_ENFD))
|
||||
return 0;
|
||||
|
||||
if (xfs_qm_dqget(mp, NULL, ip->i_d.di_projid, XFS_DQ_PROJ, 0, &dqp))
|
||||
return 0;
|
||||
dp = &dqp->q_core;
|
||||
|
||||
limit = dp->d_blk_softlimit ?
|
||||
be64_to_cpu(dp->d_blk_softlimit) :
|
||||
|
@ -234,37 +75,35 @@ xfs_qm_statvfs(
|
|||
(statp->f_files > be64_to_cpu(dp->d_icount)) ?
|
||||
(statp->f_ffree - be64_to_cpu(dp->d_icount)) : 0;
|
||||
}
|
||||
|
||||
xfs_qm_dqput(dqp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
STATIC int
|
||||
xfs_qm_syncall(
|
||||
struct bhv_desc *bhv,
|
||||
int flags,
|
||||
cred_t *credp)
|
||||
{
|
||||
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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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__ */
|
|
@ -32,6 +32,7 @@
|
|||
#include "xfs_btree.h"
|
||||
#include "xfs_acl.h"
|
||||
#include "xfs_attr.h"
|
||||
#include "xfs_vnodeops.h"
|
||||
|
||||
#include <linux/capability.h>
|
||||
#include <linux/posix_acl_xattr.h>
|
||||
|
@ -241,7 +242,7 @@ xfs_acl_vget(
|
|||
bhv_vattr_t va;
|
||||
|
||||
va.va_mask = XFS_AT_MODE;
|
||||
error = bhv_vop_getattr(vp, &va, 0, sys_cred);
|
||||
error = xfs_getattr(xfs_vtoi(vp), &va, 0);
|
||||
if (error)
|
||||
goto out;
|
||||
xfs_acl_sync_mode(va.va_mode, xfs_acl);
|
||||
|
@ -265,9 +266,10 @@ xfs_acl_vremove(
|
|||
VN_HOLD(vp);
|
||||
error = xfs_acl_allow_set(vp, kind);
|
||||
if (!error) {
|
||||
error = bhv_vop_attr_remove(vp, kind == _ACL_TYPE_DEFAULT?
|
||||
error = xfs_attr_remove(xfs_vtoi(vp),
|
||||
kind == _ACL_TYPE_DEFAULT?
|
||||
SGI_ACL_DEFAULT: SGI_ACL_FILE,
|
||||
ATTR_ROOT, sys_cred);
|
||||
ATTR_ROOT);
|
||||
if (error == ENOATTR)
|
||||
error = 0; /* 'scool */
|
||||
}
|
||||
|
@ -370,17 +372,18 @@ xfs_acl_allow_set(
|
|||
bhv_vnode_t *vp,
|
||||
int kind)
|
||||
{
|
||||
xfs_inode_t *ip = xfs_vtoi(vp);
|
||||
bhv_vattr_t va;
|
||||
int error;
|
||||
|
||||
if (vp->v_inode.i_flags & (S_IMMUTABLE|S_APPEND))
|
||||
if (vp->i_flags & (S_IMMUTABLE|S_APPEND))
|
||||
return EPERM;
|
||||
if (kind == _ACL_TYPE_DEFAULT && !VN_ISDIR(vp))
|
||||
return ENOTDIR;
|
||||
if (vp->v_vfsp->vfs_flag & VFS_RDONLY)
|
||||
if (vp->i_sb->s_flags & MS_RDONLY)
|
||||
return EROFS;
|
||||
va.va_mask = XFS_AT_UID;
|
||||
error = bhv_vop_getattr(vp, &va, 0, NULL);
|
||||
error = xfs_getattr(ip, &va, 0);
|
||||
if (error)
|
||||
return error;
|
||||
if (va.va_uid != current->fsuid && !capable(CAP_FOWNER))
|
||||
|
@ -613,7 +616,8 @@ xfs_acl_get_attr(
|
|||
|
||||
ASSERT((flags & ATTR_KERNOVAL) ? (aclp == NULL) : 1);
|
||||
flags |= ATTR_ROOT;
|
||||
*error = bhv_vop_attr_get(vp, kind == _ACL_TYPE_ACCESS ?
|
||||
*error = xfs_attr_get(xfs_vtoi(vp),
|
||||
kind == _ACL_TYPE_ACCESS ?
|
||||
SGI_ACL_FILE : SGI_ACL_DEFAULT,
|
||||
(char *)aclp, &len, flags, sys_cred);
|
||||
if (*error || (flags & ATTR_KERNOVAL))
|
||||
|
@ -651,9 +655,10 @@ xfs_acl_set_attr(
|
|||
INT_SET(newace->ae_perm, ARCH_CONVERT, ace->ae_perm);
|
||||
}
|
||||
INT_SET(newacl->acl_cnt, ARCH_CONVERT, aclp->acl_cnt);
|
||||
*error = bhv_vop_attr_set(vp, kind == _ACL_TYPE_ACCESS ?
|
||||
*error = xfs_attr_set(xfs_vtoi(vp),
|
||||
kind == _ACL_TYPE_ACCESS ?
|
||||
SGI_ACL_FILE: SGI_ACL_DEFAULT,
|
||||
(char *)newacl, len, ATTR_ROOT, sys_cred);
|
||||
(char *)newacl, len, ATTR_ROOT);
|
||||
_ACL_FREE(newacl);
|
||||
}
|
||||
|
||||
|
@ -675,7 +680,7 @@ xfs_acl_vtoacl(
|
|||
if (!error) {
|
||||
/* Got the ACL, need the mode... */
|
||||
va.va_mask = XFS_AT_MODE;
|
||||
error = bhv_vop_getattr(vp, &va, 0, sys_cred);
|
||||
error = xfs_getattr(xfs_vtoi(vp), &va, 0);
|
||||
}
|
||||
|
||||
if (error)
|
||||
|
@ -699,7 +704,7 @@ xfs_acl_vtoacl(
|
|||
int
|
||||
xfs_acl_inherit(
|
||||
bhv_vnode_t *vp,
|
||||
bhv_vattr_t *vap,
|
||||
mode_t mode,
|
||||
xfs_acl_t *pdaclp)
|
||||
{
|
||||
xfs_acl_t *cacl;
|
||||
|
@ -727,7 +732,7 @@ xfs_acl_inherit(
|
|||
return ENOMEM;
|
||||
|
||||
memcpy(cacl, pdaclp, sizeof(xfs_acl_t));
|
||||
xfs_acl_filter_mode(vap->va_mode, cacl);
|
||||
xfs_acl_filter_mode(mode, cacl);
|
||||
xfs_acl_setmode(vp, cacl, &basicperms);
|
||||
|
||||
/*
|
||||
|
@ -773,7 +778,7 @@ xfs_acl_setmode(
|
|||
* mode. The m:: bits take precedence over the g:: bits.
|
||||
*/
|
||||
va.va_mask = XFS_AT_MODE;
|
||||
error = bhv_vop_getattr(vp, &va, 0, sys_cred);
|
||||
error = xfs_getattr(xfs_vtoi(vp), &va, 0);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
|
@ -807,7 +812,7 @@ xfs_acl_setmode(
|
|||
if (gap && nomask)
|
||||
va.va_mode |= gap->ae_perm << 3;
|
||||
|
||||
return bhv_vop_setattr(vp, &va, 0, sys_cred);
|
||||
return xfs_setattr(xfs_vtoi(vp), &va, 0, sys_cred);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -50,7 +50,6 @@ typedef struct xfs_acl {
|
|||
#ifdef CONFIG_XFS_POSIX_ACL
|
||||
|
||||
struct vattr;
|
||||
struct bhv_vnode;
|
||||
struct xfs_inode;
|
||||
|
||||
extern struct kmem_zone *xfs_acl_zone;
|
||||
|
@ -58,20 +57,20 @@ extern struct kmem_zone *xfs_acl_zone;
|
|||
(zone) = kmem_zone_init(sizeof(xfs_acl_t), (name))
|
||||
#define xfs_acl_zone_destroy(zone) kmem_zone_destroy(zone)
|
||||
|
||||
extern int xfs_acl_inherit(struct bhv_vnode *, struct bhv_vattr *, xfs_acl_t *);
|
||||
extern int xfs_acl_inherit(bhv_vnode_t *, mode_t mode, xfs_acl_t *);
|
||||
extern int xfs_acl_iaccess(struct xfs_inode *, mode_t, cred_t *);
|
||||
extern int xfs_acl_vtoacl(struct bhv_vnode *, xfs_acl_t *, xfs_acl_t *);
|
||||
extern int xfs_acl_vhasacl_access(struct bhv_vnode *);
|
||||
extern int xfs_acl_vhasacl_default(struct bhv_vnode *);
|
||||
extern int xfs_acl_vset(struct bhv_vnode *, void *, size_t, int);
|
||||
extern int xfs_acl_vget(struct bhv_vnode *, void *, size_t, int);
|
||||
extern int xfs_acl_vremove(struct bhv_vnode *, int);
|
||||
extern int xfs_acl_vtoacl(bhv_vnode_t *, xfs_acl_t *, xfs_acl_t *);
|
||||
extern int xfs_acl_vhasacl_access(bhv_vnode_t *);
|
||||
extern int xfs_acl_vhasacl_default(bhv_vnode_t *);
|
||||
extern int xfs_acl_vset(bhv_vnode_t *, void *, size_t, int);
|
||||
extern int xfs_acl_vget(bhv_vnode_t *, void *, size_t, int);
|
||||
extern int xfs_acl_vremove(bhv_vnode_t *, int);
|
||||
|
||||
#define _ACL_TYPE_ACCESS 1
|
||||
#define _ACL_TYPE_DEFAULT 2
|
||||
#define _ACL_PERM_INVALID(perm) ((perm) & ~(ACL_READ|ACL_WRITE|ACL_EXECUTE))
|
||||
|
||||
#define _ACL_INHERIT(c,v,d) (xfs_acl_inherit(c,v,d))
|
||||
#define _ACL_INHERIT(c,m,d) (xfs_acl_inherit(c,m,d))
|
||||
#define _ACL_GET_ACCESS(pv,pa) (xfs_acl_vtoacl(pv,pa,NULL) == 0)
|
||||
#define _ACL_GET_DEFAULT(pv,pd) (xfs_acl_vtoacl(pv,NULL,pd) == 0)
|
||||
#define _ACL_ACCESS_EXISTS xfs_acl_vhasacl_access
|
||||
|
@ -91,7 +90,7 @@ extern int xfs_acl_vremove(struct bhv_vnode *, int);
|
|||
#define xfs_acl_vhasacl_default(v) (0)
|
||||
#define _ACL_ALLOC(a) (1) /* successfully allocate nothing */
|
||||
#define _ACL_FREE(a) ((void)0)
|
||||
#define _ACL_INHERIT(c,v,d) (0)
|
||||
#define _ACL_INHERIT(c,m,d) (0)
|
||||
#define _ACL_GET_ACCESS(pv,pa) (0)
|
||||
#define _ACL_GET_DEFAULT(pv,pd) (0)
|
||||
#define _ACL_ACCESS_EXISTS (NULL)
|
||||
|
|
|
@ -197,6 +197,10 @@ typedef struct xfs_perag
|
|||
#endif
|
||||
xfs_perag_busy_t *pagb_list; /* unstable blocks */
|
||||
atomic_t pagf_fstrms; /* # of filestreams active in this AG */
|
||||
|
||||
int pag_ici_init; /* incore inode cache initialised */
|
||||
rwlock_t pag_ici_lock; /* incore inode lock */
|
||||
struct radix_tree_root pag_ici_root; /* incore inode cache root */
|
||||
} xfs_perag_t;
|
||||
|
||||
#define XFS_AG_MAXLEVELS(mp) ((mp)->m_ag_maxlevels)
|
||||
|
|
|
@ -49,6 +49,7 @@
|
|||
#include "xfs_trans_space.h"
|
||||
#include "xfs_acl.h"
|
||||
#include "xfs_rw.h"
|
||||
#include "xfs_vnodeops.h"
|
||||
|
||||
/*
|
||||
* xfs_attr.c
|
||||
|
@ -156,10 +157,14 @@ xfs_attr_fetch(xfs_inode_t *ip, const char *name, int namelen,
|
|||
}
|
||||
|
||||
int
|
||||
xfs_attr_get(bhv_desc_t *bdp, const char *name, char *value, int *valuelenp,
|
||||
int flags, struct cred *cred)
|
||||
xfs_attr_get(
|
||||
xfs_inode_t *ip,
|
||||
const char *name,
|
||||
char *value,
|
||||
int *valuelenp,
|
||||
int flags,
|
||||
cred_t *cred)
|
||||
{
|
||||
xfs_inode_t *ip = XFS_BHVTOI(bdp);
|
||||
int error, namelen;
|
||||
|
||||
XFS_STATS_INC(xs_attr_get);
|
||||
|
@ -417,10 +422,13 @@ 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;
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -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__ */
|
|
@ -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;
|
||||
|
|
|
@ -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 *);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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__ */
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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) */
|
||||
|
||||
/*
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
||||
/*
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 = {
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
100
fs/xfs/xfs_log.c
100
fs/xfs/xfs_log.c
|
@ -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 */
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 */
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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__ */
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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)) {
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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, \
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
};
|
||||
|
|
|
@ -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
|
@ -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 */
|
Loading…
Reference in New Issue