diff options
90 files changed, 2762 insertions, 4739 deletions
diff --git a/fs/xfs/Makefile-linux-2.6 b/fs/xfs/Makefile-linux-2.6 index e7a9a83f0087..d1491aa7a0e2 100644 --- a/fs/xfs/Makefile-linux-2.6 +++ b/fs/xfs/Makefile-linux-2.6 @@ -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 diff --git a/fs/xfs/linux-2.6/xfs_aops.c b/fs/xfs/linux-2.6/xfs_aops.c index 52bd08c0a278..2e34b104107c 100644 --- a/fs/xfs/linux-2.6/xfs_aops.c +++ b/fs/xfs/linux-2.6/xfs_aops.c @@ -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); } diff --git a/fs/xfs/linux-2.6/xfs_aops.h b/fs/xfs/linux-2.6/xfs_aops.h index 2244e516b66a..3ba0631a3818 100644 --- a/fs/xfs/linux-2.6/xfs_aops.h +++ b/fs/xfs/linux-2.6/xfs_aops.h @@ -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 */ diff --git a/fs/xfs/linux-2.6/xfs_buf.c b/fs/xfs/linux-2.6/xfs_buf.c index 39f44ee572e8..b9c8589e05c2 100644 --- a/fs/xfs/linux-2.6/xfs_buf.c +++ b/fs/xfs/linux-2.6/xfs_buf.c @@ -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); diff --git a/fs/xfs/linux-2.6/xfs_export.c b/fs/xfs/linux-2.6/xfs_export.c index e3a5fedac1ba..726449d4fd22 100644 --- a/fs/xfs/linux-2.6/xfs_export.c +++ b/fs/xfs/linux-2.6/xfs_export.c @@ -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); diff --git a/fs/xfs/linux-2.6/xfs_file.c b/fs/xfs/linux-2.6/xfs_file.c index 0d4001eafd16..fb8dd34041eb 100644 --- a/fs/xfs/linux-2.6/xfs_file.c +++ b/fs/xfs/linux-2.6/xfs_file.c @@ -37,6 +37,7 @@ #include "xfs_error.h" #include "xfs_rw.h" #include "xfs_ioctl32.h" +#include "xfs_vnodeops.h" #include <linux/dcache.h> #include <linux/smp_lock.h> @@ -55,13 +56,12 @@ __xfs_file_read( loff_t pos) { struct file *file = iocb->ki_filp; - bhv_vnode_t *vp = vn_from_inode(file->f_path.dentry->d_inode); BUG_ON(iocb->ki_pos != pos); if (unlikely(file->f_flags & O_DIRECT)) ioflags |= IO_ISDIRECT; - return bhv_vop_read(vp, iocb, iov, nr_segs, &iocb->ki_pos, - ioflags, NULL); + return xfs_read(XFS_I(file->f_path.dentry->d_inode), iocb, iov, + nr_segs, &iocb->ki_pos, ioflags); } STATIC ssize_t @@ -93,14 +93,12 @@ __xfs_file_write( loff_t pos) { struct file *file = iocb->ki_filp; - struct inode *inode = file->f_mapping->host; - bhv_vnode_t *vp = vn_from_inode(inode); BUG_ON(iocb->ki_pos != pos); if (unlikely(file->f_flags & O_DIRECT)) ioflags |= IO_ISDIRECT; - return bhv_vop_write(vp, iocb, iov, nr_segs, &iocb->ki_pos, - ioflags, NULL); + return xfs_write(XFS_I(file->f_mapping->host), iocb, iov, nr_segs, + &iocb->ki_pos, ioflags); } STATIC ssize_t @@ -131,8 +129,8 @@ xfs_file_splice_read( size_t len, unsigned int flags) { - return bhv_vop_splice_read(vn_from_inode(infilp->f_path.dentry->d_inode), - infilp, ppos, pipe, len, flags, 0, NULL); + return xfs_splice_read(XFS_I(infilp->f_path.dentry->d_inode), + infilp, ppos, pipe, len, flags, 0); } STATIC ssize_t @@ -143,9 +141,8 @@ xfs_file_splice_read_invis( size_t len, unsigned int flags) { - return bhv_vop_splice_read(vn_from_inode(infilp->f_path.dentry->d_inode), - infilp, ppos, pipe, len, flags, IO_INVIS, - NULL); + return xfs_splice_read(XFS_I(infilp->f_path.dentry->d_inode), + infilp, ppos, pipe, len, flags, IO_INVIS); } STATIC ssize_t @@ -156,8 +153,8 @@ xfs_file_splice_write( size_t len, unsigned int flags) { - return bhv_vop_splice_write(vn_from_inode(outfilp->f_path.dentry->d_inode), - pipe, outfilp, ppos, len, flags, 0, NULL); + return xfs_splice_write(XFS_I(outfilp->f_path.dentry->d_inode), + pipe, outfilp, ppos, len, flags, 0); } STATIC ssize_t @@ -168,9 +165,8 @@ xfs_file_splice_write_invis( size_t len, unsigned int flags) { - return bhv_vop_splice_write(vn_from_inode(outfilp->f_path.dentry->d_inode), - pipe, outfilp, ppos, len, flags, IO_INVIS, - NULL); + return xfs_splice_write(XFS_I(outfilp->f_path.dentry->d_inode), + pipe, outfilp, ppos, len, flags, IO_INVIS); } STATIC int @@ -180,7 +176,7 @@ xfs_file_open( { if (!(filp->f_flags & O_LARGEFILE) && i_size_read(inode) > MAX_NON_LFS) return -EFBIG; - return -bhv_vop_open(vn_from_inode(inode), NULL); + return -xfs_open(XFS_I(inode)); } STATIC int @@ -188,11 +184,7 @@ xfs_file_release( struct inode *inode, struct file *filp) { - bhv_vnode_t *vp = vn_from_inode(inode); - - if (vp) - return -bhv_vop_release(vp); - return 0; + return -xfs_release(XFS_I(inode)); } STATIC int @@ -201,14 +193,13 @@ xfs_file_fsync( struct dentry *dentry, int datasync) { - bhv_vnode_t *vp = vn_from_inode(dentry->d_inode); int flags = FSYNC_WAIT; if (datasync) flags |= FSYNC_DATA; - if (VN_TRUNC(vp)) - VUNTRUNCATE(vp); - return -bhv_vop_fsync(vp, flags, NULL, (xfs_off_t)0, (xfs_off_t)-1); + xfs_iflags_clear(XFS_I(dentry->d_inode), XFS_ITRUNCATED); + return -xfs_fsync(XFS_I(dentry->d_inode), flags, + (xfs_off_t)0, (xfs_off_t)-1); } #ifdef CONFIG_XFS_DMAPI @@ -233,74 +224,30 @@ xfs_file_readdir( void *dirent, filldir_t filldir) { - int error = 0; - bhv_vnode_t *vp = vn_from_inode(filp->f_path.dentry->d_inode); - uio_t uio; - iovec_t iov; - int eof = 0; - caddr_t read_buf; - int namelen, size = 0; - size_t rlen = PAGE_CACHE_SIZE; - xfs_off_t start_offset, curr_offset; - xfs_dirent_t *dbp = NULL; - - /* Try fairly hard to get memory */ - do { - if ((read_buf = kmalloc(rlen, GFP_KERNEL))) - break; - rlen >>= 1; - } while (rlen >= 1024); - - if (read_buf == NULL) - return -ENOMEM; - - uio.uio_iov = &iov; - uio.uio_segflg = UIO_SYSSPACE; - curr_offset = filp->f_pos; - if (filp->f_pos != 0x7fffffff) - uio.uio_offset = filp->f_pos; - else - uio.uio_offset = 0xffffffff; - - while (!eof) { - uio.uio_resid = iov.iov_len = rlen; - iov.iov_base = read_buf; - uio.uio_iovcnt = 1; - - start_offset = uio.uio_offset; - - error = bhv_vop_readdir(vp, &uio, NULL, &eof); - if ((uio.uio_offset == start_offset) || error) { - size = 0; - break; - } - - size = rlen - uio.uio_resid; - dbp = (xfs_dirent_t *)read_buf; - while (size > 0) { - namelen = strlen(dbp->d_name); - - if (filldir(dirent, dbp->d_name, namelen, - (loff_t) curr_offset & 0x7fffffff, - (ino_t) dbp->d_ino, - DT_UNKNOWN)) { - goto done; - } - size -= dbp->d_reclen; - curr_offset = (loff_t)dbp->d_off /* & 0x7fffffff */; - dbp = (xfs_dirent_t *)((char *)dbp + dbp->d_reclen); - } - } -done: - if (!error) { - if (size == 0) - filp->f_pos = uio.uio_offset & 0x7fffffff; - else if (dbp) - filp->f_pos = curr_offset; - } + struct inode *inode = filp->f_path.dentry->d_inode; + xfs_inode_t *ip = XFS_I(inode); + int error; + size_t bufsize; + + /* + * The Linux API doesn't pass down the total size of the buffer + * we read into down to the filesystem. With the filldir concept + * it's not needed for correct information, but the XFS dir2 leaf + * code wants an estimate of the buffer size to calculate it's + * readahead window and size the buffers used for mapping to + * physical blocks. + * + * Try to give it an estimate that's good enough, maybe at some + * point we can change the ->readdir prototype to include the + * buffer size. + */ + bufsize = (size_t)min_t(loff_t, PAGE_SIZE, inode->i_size); - kfree(read_buf); - return -error; + error = xfs_readdir(ip, dirent, bufsize, + (xfs_off_t *)&filp->f_pos, filldir); + if (error) + return -error; + return 0; } STATIC int @@ -312,7 +259,7 @@ xfs_file_mmap( vma->vm_flags |= VM_CAN_NONLINEAR; #ifdef CONFIG_XFS_DMAPI - if (vn_from_inode(filp->f_path.dentry->d_inode)->v_vfsp->vfs_flag & VFS_DMI) + if (XFS_M(filp->f_path.dentry->d_inode->i_sb)->m_flags & XFS_MOUNT_DMAPI) vma->vm_ops = &xfs_dmapi_file_vm_ops; #endif /* CONFIG_XFS_DMAPI */ @@ -328,10 +275,9 @@ xfs_file_ioctl( { int error; struct inode *inode = filp->f_path.dentry->d_inode; - bhv_vnode_t *vp = vn_from_inode(inode); - error = bhv_vop_ioctl(vp, inode, filp, 0, cmd, (void __user *)p); - VMODIFY(vp); + error = xfs_ioctl(XFS_I(inode), filp, 0, cmd, (void __user *)p); + xfs_iflags_set(XFS_I(inode), XFS_IMODIFIED); /* NOTE: some of the ioctl's return positive #'s as a * byte count indicating success, such as @@ -350,10 +296,9 @@ xfs_file_ioctl_invis( { int error; struct inode *inode = filp->f_path.dentry->d_inode; - bhv_vnode_t *vp = vn_from_inode(inode); - error = bhv_vop_ioctl(vp, inode, filp, IO_INVIS, cmd, (void __user *)p); - VMODIFY(vp); + error = xfs_ioctl(XFS_I(inode), filp, IO_INVIS, cmd, (void __user *)p); + xfs_iflags_set(XFS_I(inode), XFS_IMODIFIED); /* NOTE: some of the ioctl's return positive #'s as a * byte count indicating success, such as @@ -371,16 +316,14 @@ xfs_vm_mprotect( struct vm_area_struct *vma, unsigned int newflags) { - bhv_vnode_t *vp = vn_from_inode(vma->vm_file->f_path.dentry->d_inode); + struct inode *inode = vma->vm_file->f_path.dentry->d_inode; + struct xfs_mount *mp = XFS_M(inode->i_sb); int error = 0; - if (vp->v_vfsp->vfs_flag & VFS_DMI) { + if (mp->m_flags & XFS_MOUNT_DMAPI) { if ((vma->vm_flags & VM_MAYSHARE) && - (newflags & VM_WRITE) && !(vma->vm_flags & VM_WRITE)) { - xfs_mount_t *mp = XFS_VFSTOM(vp->v_vfsp); - + (newflags & VM_WRITE) && !(vma->vm_flags & VM_WRITE)) error = XFS_SEND_MMAP(mp, vma, VM_WRITE); - } } return error; } @@ -397,18 +340,17 @@ STATIC int xfs_file_open_exec( struct inode *inode) { - bhv_vnode_t *vp = vn_from_inode(inode); + struct xfs_mount *mp = XFS_M(inode->i_sb); - if (unlikely(vp->v_vfsp->vfs_flag & VFS_DMI)) { - xfs_mount_t *mp = XFS_VFSTOM(vp->v_vfsp); - xfs_inode_t *ip = xfs_vtoi(vp); + if (unlikely(mp->m_flags & XFS_MOUNT_DMAPI)) { + if (DM_EVENT_ENABLED(XFS_I(inode), DM_EVENT_READ)) { + bhv_vnode_t *vp = vn_from_inode(inode); - if (!ip) - return -EINVAL; - if (DM_EVENT_ENABLED(vp->v_vfsp, ip, DM_EVENT_READ)) - return -XFS_SEND_DATA(mp, DM_EVENT_READ, vp, - 0, 0, 0, NULL); + return -XFS_SEND_DATA(mp, DM_EVENT_READ, + vp, 0, 0, 0, NULL); + } } + return 0; } #endif /* HAVE_FOP_OPEN_EXEC */ diff --git a/fs/xfs/linux-2.6/xfs_fs_subr.c b/fs/xfs/linux-2.6/xfs_fs_subr.c index 2eb87cd082af..ac6d34cc355d 100644 --- a/fs/xfs/linux-2.6/xfs_fs_subr.c +++ b/fs/xfs/linux-2.6/xfs_fs_subr.c @@ -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; } diff --git a/fs/xfs/linux-2.6/xfs_fs_subr.h b/fs/xfs/linux-2.6/xfs_fs_subr.h index c1b53118a303..82bb19b2599e 100644 --- a/fs/xfs/linux-2.6/xfs_fs_subr.h +++ b/fs/xfs/linux-2.6/xfs_fs_subr.h @@ -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__ */ diff --git a/fs/xfs/linux-2.6/xfs_globals.c b/fs/xfs/linux-2.6/xfs_globals.c index 81565dea9af7..9febf9dc999d 100644 --- a/fs/xfs/linux-2.6/xfs_globals.c +++ b/fs/xfs/linux-2.6/xfs_globals.c @@ -20,11 +20,6 @@ #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. * 100ths of a second). diff --git a/fs/xfs/linux-2.6/xfs_globals.h b/fs/xfs/linux-2.6/xfs_globals.h index e1a22bfcf865..2770b0085ee8 100644 --- a/fs/xfs/linux-2.6/xfs_globals.h +++ b/fs/xfs/linux-2.6/xfs_globals.h @@ -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__ */ diff --git a/fs/xfs/linux-2.6/xfs_ioctl.c b/fs/xfs/linux-2.6/xfs_ioctl.c index 5917808abbd6..ffec630e7db7 100644 --- a/fs/xfs/linux-2.6/xfs_ioctl.c +++ b/fs/xfs/linux-2.6/xfs_ioctl.c @@ -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, @@ -681,37 +709,37 @@ xfs_ioc_xattr( 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; } @@ -1140,6 +1170,42 @@ xfs_di2lxflags( } 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, xfs_inode_t *ip, @@ -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; diff --git a/fs/xfs/linux-2.6/xfs_ioctl32.c b/fs/xfs/linux-2.6/xfs_ioctl32.c index 42319d75aaab..0046bdd5b7f1 100644 --- a/fs/xfs/linux-2.6/xfs_ioctl32.c +++ b/fs/xfs/linux-2.6/xfs_ioctl32.c @@ -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; } diff --git a/fs/xfs/linux-2.6/xfs_iops.c b/fs/xfs/linux-2.6/xfs_iops.c index e0e06dd4bef2..ac50f8a37582 100644 --- a/fs/xfs/linux-2.6/xfs_iops.c +++ b/fs/xfs/linux-2.6/xfs_iops.c @@ -46,6 +46,7 @@ #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> @@ -53,22 +54,6 @@ #include <linux/security.h> /* - * Get a XFS inode from a given vnode. - */ -xfs_inode_t * -xfs_vtoi( - bhv_vnode_t *vp) -{ - bhv_desc_t *bdp; - - bdp = bhv_lookup_range(VN_BHV_HEAD(vp), - VNODE_POSITION_XFS, VNODE_POSITION_XFS); - if (unlikely(bdp == NULL)) - return NULL; - return XFS_BHVTOI(bdp); -} - -/* * Bring the atime in the XFS inode uptodate. * Used before logging the inode to disk or when the Linux inode goes away. */ @@ -80,9 +65,8 @@ xfs_synchronize_atime( vp = XFS_ITOV_NULL(ip); if (vp) { - struct inode *inode = &vp->v_inode; - ip->i_d.di_atime.t_sec = (__int32_t)inode->i_atime.tv_sec; - ip->i_d.di_atime.t_nsec = (__int32_t)inode->i_atime.tv_nsec; + ip->i_d.di_atime.t_sec = (__int32_t)vp->i_atime.tv_sec; + ip->i_d.di_atime.t_nsec = (__int32_t)vp->i_atime.tv_nsec; } } @@ -195,18 +179,19 @@ xfs_ichgtime_fast( */ STATIC void xfs_validate_fields( - struct inode *ip, - bhv_vattr_t *vattr) + struct inode *inode) { - vattr->va_mask = XFS_AT_NLINK|XFS_AT_SIZE|XFS_AT_NBLOCKS; - if (!bhv_vop_getattr(vn_from_inode(ip), vattr, ATTR_LAZY, NULL)) { - ip->i_nlink = vattr->va_nlink; - ip->i_blocks = vattr->va_nblocks; - - /* we're under i_sem so i_size can't change under us */ - if (i_size_read(ip) != vattr->va_size) - i_size_write(ip, vattr->va_size); - } + struct xfs_inode *ip = XFS_I(inode); + loff_t size; + + inode->i_nlink = ip->i_d.di_nlink; + inode->i_blocks = + XFS_FSB_TO_BB(ip->i_mount, ip->i_d.di_nblocks + + ip->i_delayed_blks); + /* we're under i_sem so i_size can't change under us */ + size = XFS_ISIZE(ip); + if (i_size_read(inode) != size) + i_size_write(inode, size); } /* @@ -233,9 +218,10 @@ xfs_init_security( return -error; } - error = bhv_vop_attr_set(vp, name, value, length, ATTR_SECURE, NULL); + error = xfs_attr_set(XFS_I(ip), name, value, + length, ATTR_SECURE); if (!error) - VMODIFY(vp); + xfs_iflags_set(XFS_I(ip), XFS_IMODIFIED); kfree(name); kfree(value); @@ -256,7 +242,7 @@ xfs_has_fs_struct(struct task_struct *task) STATIC void xfs_cleanup_inode( - bhv_vnode_t *dvp, + struct inode *dir, bhv_vnode_t *vp, struct dentry *dentry, int mode) @@ -272,9 +258,9 @@ xfs_cleanup_inode( teardown.d_name = dentry->d_name; if (S_ISDIR(mode)) - bhv_vop_rmdir(dvp, &teardown, NULL); + xfs_rmdir(XFS_I(dir), &teardown); else - bhv_vop_remove(dvp, &teardown, NULL); + xfs_remove(XFS_I(dir), &teardown); VN_RELE(vp); } @@ -286,7 +272,6 @@ xfs_vn_mknod( dev_t rdev) { struct inode *ip; - bhv_vattr_t vattr = { 0 }; bhv_vnode_t *vp = NULL, *dvp = vn_from_inode(dir); xfs_acl_t *default_acl = NULL; attrexists_t test_default_acl = _ACL_DEFAULT_EXISTS; @@ -312,19 +297,14 @@ xfs_vn_mknod( if (IS_POSIXACL(dir) && !default_acl && xfs_has_fs_struct(current)) mode &= ~current->fs->umask; - vattr.va_mask = XFS_AT_TYPE|XFS_AT_MODE; - vattr.va_mode = mode; - switch (mode & S_IFMT) { case S_IFCHR: case S_IFBLK: case S_IFIFO: case S_IFSOCK: - vattr.va_rdev = sysv_encode_dev(rdev); - vattr.va_mask |= XFS_AT_RDEV; - /*FALLTHROUGH*/ + rdev = sysv_encode_dev(rdev); case S_IFREG: - error = bhv_vop_create(dvp, dentry, &vattr, &vp, NULL); + error = xfs_create(XFS_I(dir), dentry, mode, rdev, &vp, NULL); break; case S_IFDIR: - error = bhv_vop_mkdir(dvp, dentry, &vattr, &vp, NULL); + error = xfs_mkdir(XFS_I(dir), dentry, mode, &vp, NULL); break; default: error = EINVAL; @@ -334,16 +314,16 @@ xfs_vn_mknod( if (unlikely(!error)) { error = xfs_init_security(vp, dir); if (error) - xfs_cleanup_inode(dvp, vp, dentry, mode); + xfs_cleanup_inode(dir, vp, dentry, mode); } if (unlikely(default_acl)) { if (!error) { - error = _ACL_INHERIT(vp, &vattr, default_acl); + error = _ACL_INHERIT(vp, mode, default_acl); if (!error) - VMODIFY(vp); + xfs_iflags_set(XFS_I(vp), XFS_IMODIFIED); else - xfs_cleanup_inode(dvp, vp, dentry, mode); + xfs_cleanup_inode(dir, vp, dentry, mode); } _ACL_FREE(default_acl); } @@ -355,9 +335,9 @@ xfs_vn_mknod( if (S_ISCHR(mode) || S_ISBLK(mode)) ip->i_rdev = rdev; else if (S_ISDIR(mode)) - xfs_validate_fields(ip, &vattr); + xfs_validate_fields(ip); d_instantiate(dentry, ip); - xfs_validate_fields(dir, &vattr); + xfs_validate_fields(dir); } return -error; } @@ -387,13 +367,13 @@ xfs_vn_lookup( struct dentry *dentry, struct nameidata *nd) { - bhv_vnode_t *vp = vn_from_inode(dir), *cvp; + bhv_vnode_t *cvp; int error; if (dentry->d_name.len >= MAXNAMELEN) return ERR_PTR(-ENAMETOOLONG); - error = bhv_vop_lookup(vp, dentry, &cvp, 0, NULL, NULL); + error = xfs_lookup(XFS_I(dir), dentry, &cvp); if (unlikely(error)) { if (unlikely(error != ENOENT)) return ERR_PTR(-error); @@ -411,22 +391,19 @@ xfs_vn_link( struct dentry *dentry) { struct inode *ip; /* inode of guy being linked to */ - bhv_vnode_t *tdvp; /* target directory for new name/link */ bhv_vnode_t *vp; /* vp of name being linked */ - bhv_vattr_t vattr; int error; ip = old_dentry->d_inode; /* inode being linked to */ - tdvp = vn_from_inode(dir); vp = vn_from_inode(ip); VN_HOLD(vp); - error = bhv_vop_link(tdvp, vp, dentry, NULL); + error = xfs_link(XFS_I(dir), vp, dentry); if (unlikely(error)) { VN_RELE(vp); } else { - VMODIFY(tdvp); - xfs_validate_fields(ip, &vattr); + xfs_iflags_set(XFS_I(dir), XFS_IMODIFIED); + xfs_validate_fields(ip); d_instantiate(dentry, ip); } return -error; @@ -438,17 +415,14 @@ xfs_vn_unlink( struct dentry *dentry) { struct inode *inode; - bhv_vnode_t *dvp; /* directory containing name to remove */ - bhv_vattr_t vattr; int error; inode = dentry->d_inode; - dvp = vn_from_inode(dir); - error = bhv_vop_remove(dvp, dentry, NULL); + error = xfs_remove(XFS_I(dir), dentry); if (likely(!error)) { - xfs_validate_fields(dir, &vattr); /* size needs update */ - xfs_validate_fields(inode, &vattr); + xfs_validate_fields(dir); /* size needs update */ + xfs_validate_fields(inode); } return -error; } @@ -460,28 +434,26 @@ xfs_vn_symlink( const char *symname) { struct inode *ip; - bhv_vattr_t va = { 0 }; - bhv_vnode_t *dvp; /* directory containing name of symlink */ bhv_vnode_t *cvp; /* used to lookup symlink to put in dentry */ int error; + mode_t mode; - dvp = vn_from_inode(dir); cvp = NULL; - va.va_mode = S_IFLNK | + mode = S_IFLNK | (irix_symlink_mode ? 0777 & ~current->fs->umask : S_IRWXUGO); - va.va_mask = XFS_AT_TYPE|XFS_AT_MODE; - error = bhv_vop_symlink(dvp, dentry, &va, (char *)symname, &cvp, NULL); + error = xfs_symlink(XFS_I(dir), dentry, (char *)symname, mode, + &cvp, NULL); if (likely(!error && cvp)) { error = xfs_init_security(cvp, dir); if (likely(!error)) { ip = vn_to_inode(cvp); d_instantiate(dentry, ip); - xfs_validate_fields(dir, &va); - xfs_validate_fields(ip, &va); + xfs_validate_fields(dir); + xfs_validate_fields(ip); } else { - xfs_cleanup_inode(dvp, cvp, dentry, 0); + xfs_cleanup_inode(dir, cvp, dentry, 0); } } return -error; @@ -493,14 +465,12 @@ xfs_vn_rmdir( struct dentry *dentry) { struct inode *inode = dentry->d_inode; - bhv_vnode_t *dvp = vn_from_inode(dir); - bhv_vattr_t vattr; int error; - error = bhv_vop_rmdir(dvp, dentry, NULL); + error = xfs_rmdir(XFS_I(dir), dentry); if (likely(!error)) { - xfs_validate_fields(inode, &vattr); - xfs_validate_fields(dir, &vattr); + xfs_validate_fields(inode); + xfs_validate_fields(dir); } return -error; } @@ -513,21 +483,18 @@ xfs_vn_rename( struct dentry *ndentry) { struct inode *new_inode = ndentry->d_inode; - bhv_vnode_t *fvp; /* from directory */ bhv_vnode_t *tvp; /* target directory */ - bhv_vattr_t vattr; int error; - fvp = vn_from_inode(odir); tvp = vn_from_inode(ndir); - error = bhv_vop_rename(fvp, odentry, tvp, ndentry, NULL); + error = xfs_rename(XFS_I(odir), odentry, tvp, ndentry); if (likely(!error)) { if (new_inode) - xfs_validate_fields(new_inode, &vattr); - xfs_validate_fields(odir, &vattr); + xfs_validate_fields(new_inode); + xfs_validate_fields(odir); if (ndir != odir) - xfs_validate_fields(ndir, &vattr); + xfs_validate_fields(ndir); } return -error; } @@ -542,50 +509,25 @@ xfs_vn_follow_link( struct dentry *dentry, struct nameidata *nd) { - bhv_vnode_t *vp; - uio_t *uio; - iovec_t iov; - int error; char *link; - - ASSERT(dentry); - ASSERT(nd); + int error = -ENOMEM; link = kmalloc(MAXPATHLEN+1, GFP_KERNEL); - if (!link) { - nd_set_link(nd, ERR_PTR(-ENOMEM)); - return NULL; - } - - uio = kmalloc(sizeof(uio_t), GFP_KERNEL); - if (!uio) { - kfree(link); - nd_set_link(nd, ERR_PTR(-ENOMEM)); - return NULL; - } - - vp = vn_from_inode(dentry->d_inode); - - iov.iov_base = link; - iov.iov_len = MAXPATHLEN; + if (!link) + goto out_err; - uio->uio_iov = &iov; - uio->uio_offset = 0; - uio->uio_segflg = UIO_SYSSPACE; - uio->uio_resid = MAXPATHLEN; - uio->uio_iovcnt = 1; - - error = bhv_vop_readlink(vp, uio, 0, NULL); - if (unlikely(error)) { - kfree(link); - link = ERR_PTR(-error); - } else { - link[MAXPATHLEN - uio->uio_resid] = '\0'; - } - kfree(uio); + error = -xfs_readlink(XFS_I(dentry->d_inode), link); + if (unlikely(error)) + goto out_kfree; nd_set_link(nd, link); return NULL; + + out_kfree: + kfree(link); + out_err: + nd_set_link(nd, ERR_PTR(error)); + return NULL; } STATIC void @@ -607,7 +549,7 @@ xfs_vn_permission( int mode, struct nameidata *nd) { - return -bhv_vop_access(vn_from_inode(inode), mode << 6, NULL); + return -xfs_access(XFS_I(inode), mode << 6, NULL); } #else #define xfs_vn_permission NULL @@ -620,11 +562,10 @@ xfs_vn_getattr( struct kstat *stat) { struct inode *inode = dentry->d_inode; - bhv_vnode_t *vp = vn_from_inode(inode); bhv_vattr_t vattr = { .va_mask = XFS_AT_STAT }; int error; - error = bhv_vop_getattr(vp, &vattr, ATTR_LAZY, NULL); + error = xfs_getattr(XFS_I(inode), &vattr, ATTR_LAZY); if (likely(!error)) { stat->size = i_size_read(inode); stat->dev = inode->i_sb->s_dev; @@ -652,7 +593,6 @@ xfs_vn_setattr( { struct inode *inode = dentry->d_inode; unsigned int ia_valid = attr->ia_valid; - bhv_vnode_t *vp = vn_from_inode(inode); bhv_vattr_t vattr = { 0 }; int flags = 0; int error; @@ -696,9 +636,9 @@ xfs_vn_setattr( flags |= ATTR_NONBLOCK; #endif - error = bhv_vop_setattr(vp, &vattr, flags, NULL); + error = xfs_setattr(XFS_I(inode), &vattr, flags, NULL); if (likely(!error)) - __vn_revalidate(vp, &vattr); + __vn_revalidate(vn_from_inode(inode), &vattr); return -error; } diff --git a/fs/xfs/linux-2.6/xfs_iops.h b/fs/xfs/linux-2.6/xfs_iops.h index 95a69398fce0..14d0deb7afff 100644 --- a/fs/xfs/linux-2.6/xfs_iops.h +++ b/fs/xfs/linux-2.6/xfs_iops.h @@ -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__ */ diff --git a/fs/xfs/linux-2.6/xfs_linux.h b/fs/xfs/linux-2.6/xfs_linux.h index 330c4ba9d404..dc3752de22da 100644 --- a/fs/xfs/linux-2.6/xfs_linux.h +++ b/fs/xfs/linux-2.6/xfs_linux.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> diff --git a/fs/xfs/linux-2.6/xfs_lrw.c b/fs/xfs/linux-2.6/xfs_lrw.c index 7e7aeb4c8a08..d6a8dddb2268 100644 --- a/fs/xfs/linux-2.6/xfs_lrw.c +++ b/fs/xfs/linux-2.6/xfs_lrw.c @@ -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); diff --git a/fs/xfs/linux-2.6/xfs_lrw.h b/fs/xfs/linux-2.6/xfs_lrw.h index 7c60a1eed88b..4b7747a828d9 100644 --- a/fs/xfs/linux-2.6/xfs_lrw.h +++ b/fs/xfs/linux-2.6/xfs_lrw.h @@ -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__ */ diff --git a/fs/xfs/linux-2.6/xfs_super.c b/fs/xfs/linux-2.6/xfs_super.c index 9c7d8202088f..8cb63c60c048 100644 --- a/fs/xfs/linux-2.6/xfs_super.c +++ b/fs/xfs/linux-2.6/xfs_super.c @@ -46,6 +46,8 @@ #include "xfs_attr.h" #include "xfs_buf_item.h" #include "xfs_utils.h" +#include "xfs_vnodeops.h" +#include "xfs_vfsops.h" #include "xfs_version.h" #include <linux/namei.h> @@ -196,23 +198,20 @@ xfs_revalidate_inode( inode->i_flags |= S_NOATIME; else inode->i_flags &= ~S_NOATIME; - vp->v_flag &= ~VMODIFIED; + xfs_iflags_clear(ip, XFS_IMODIFIED); } void xfs_initialize_vnode( - bhv_desc_t *bdp, + struct xfs_mount *mp, bhv_vnode_t *vp, - bhv_desc_t *inode_bhv, - int unlock) + struct xfs_inode *ip) { - xfs_inode_t *ip = XFS_BHVTOI(inode_bhv); struct inode *inode = vn_to_inode(vp); - if (!inode_bhv->bd_vobj) { - vp->v_vfsp = bhvtovfs(bdp); - bhv_desc_init(inode_bhv, ip, vp, &xfs_vnodeops); - bhv_insert(VN_BHV_HEAD(vp), inode_bhv); + if (!ip->i_vnode) { + ip->i_vnode = vp; + inode->i_private = ip; } /* @@ -222,8 +221,8 @@ xfs_initialize_vnode( * second time once the inode is properly set up, and then we can * finish our work. */ - if (ip->i_d.di_mode != 0 && unlock && (inode->i_state & I_NEW)) { - xfs_revalidate_inode(XFS_BHVTOM(bdp), vp, ip); + if (ip->i_d.di_mode != 0 && (inode->i_state & I_NEW)) { + xfs_revalidate_inode(mp, vp, ip); xfs_set_inodeops(inode); xfs_iflags_clear(ip, XFS_INEW); @@ -409,19 +408,22 @@ xfs_fs_write_inode( struct inode *inode, int sync) { - bhv_vnode_t *vp = vn_from_inode(inode); int error = 0, flags = FLUSH_INODE; - if (vp) { - vn_trace_entry(vp, __FUNCTION__, (inst_t *)__return_address); - if (sync) { - filemap_fdatawait(inode->i_mapping); - flags |= FLUSH_SYNC; - } - error = bhv_vop_iflush(vp, flags); - if (error == EAGAIN) - error = sync? bhv_vop_iflush(vp, flags | FLUSH_LOG) : 0; + vn_trace_entry(XFS_I(inode), __FUNCTION__, + (inst_t *)__return_address); + if (sync) { + filemap_fdatawait(inode->i_mapping); + flags |= FLUSH_SYNC; } + error = xfs_inode_flush(XFS_I(inode), flags); + /* + * if we failed to write out the inode then mark + * it dirty again so we'll try again later. + */ + if (error) + mark_inode_dirty_sync(inode); + return -error; } @@ -429,35 +431,27 @@ STATIC void xfs_fs_clear_inode( struct inode *inode) { - bhv_vnode_t *vp = vn_from_inode(inode); - - vn_trace_entry(vp, __FUNCTION__, (inst_t *)__return_address); - - XFS_STATS_INC(vn_rele); - XFS_STATS_INC(vn_remove); - XFS_STATS_INC(vn_reclaim); - XFS_STATS_DEC(vn_active); + xfs_inode_t *ip = XFS_I(inode); /* - * This can happen because xfs_iget_core calls xfs_idestroy if we + * ip can be null when xfs_iget_core calls xfs_idestroy if we * find an inode with di_mode == 0 but without IGET_CREATE set. */ - if (VNHEAD(vp)) - bhv_vop_inactive(vp, NULL); - - VN_LOCK(vp); - vp->v_flag &= ~VMODIFIED; - VN_UNLOCK(vp, 0); - - if (VNHEAD(vp)) - if (bhv_vop_reclaim(vp)) - panic("%s: cannot reclaim 0x%p\n", __FUNCTION__, vp); - - ASSERT(VNHEAD(vp) == NULL); + if (ip) { + vn_trace_entry(ip, __FUNCTION__, (inst_t *)__return_address); + + XFS_STATS_INC(vn_rele); + XFS_STATS_INC(vn_remove); + XFS_STATS_INC(vn_reclaim); + XFS_STATS_DEC(vn_active); + + xfs_inactive(ip); + xfs_iflags_clear(ip, XFS_IMODIFIED); + if (xfs_reclaim(ip)) + panic("%s: cannot reclaim 0x%p\n", __FUNCTION__, inode); + } -#ifdef XFS_VNODE_TRACE - ktrace_free(vp->v_trace); -#endif + ASSERT(XFS_I(inode) == NULL); } /* @@ -469,9 +463,9 @@ xfs_fs_clear_inode( */ STATIC void xfs_syncd_queue_work( - struct bhv_vfs *vfs, + struct xfs_mount *mp, void *data, - void (*syncer)(bhv_vfs_t *, void *)) + void (*syncer)(struct xfs_mount *, void *)) { struct bhv_vfs_sync_work *work; @@ -479,11 +473,11 @@ xfs_syncd_queue_work( INIT_LIST_HEAD(&work->w_list); work->w_syncer = syncer; work->w_data = data; - work->w_vfs = vfs; - spin_lock(&vfs->vfs_sync_lock); - list_add_tail(&work->w_list, &vfs->vfs_sync_list); - spin_unlock(&vfs->vfs_sync_lock); - wake_up_process(vfs->vfs_sync_task); + work->w_mount = mp; + spin_lock(&mp->m_sync_lock); + list_add_tail(&work->w_list, &mp->m_sync_list); + spin_unlock(&mp->m_sync_lock); + wake_up_process(mp->m_sync_task); } /* @@ -494,22 +488,22 @@ xfs_syncd_queue_work( */ STATIC void xfs_flush_inode_work( - bhv_vfs_t *vfs, - void *inode) + struct xfs_mount *mp, + void *arg) { - filemap_flush(((struct inode *)inode)->i_mapping); - iput((struct inode *)inode); + struct inode *inode = arg; + filemap_flush(inode->i_mapping); + iput(inode); } void xfs_flush_inode( xfs_inode_t *ip) { - struct inode *inode = vn_to_inode(XFS_ITOV(ip)); - struct bhv_vfs *vfs = XFS_MTOVFS(ip->i_mount); + struct inode *inode = ip->i_vnode; igrab(inode); - xfs_syncd_queue_work(vfs, inode, xfs_flush_inode_work); + xfs_syncd_queue_work(ip->i_mount, inode, xfs_flush_inode_work); delay(msecs_to_jiffies(500)); } @@ -519,11 +513,12 @@ xfs_flush_inode( */ STATIC void xfs_flush_device_work( - bhv_vfs_t *vfs, - void *inode) + struct xfs_mount *mp, + void *arg) { - sync_blockdev(vfs->vfs_super->s_bdev); - iput((struct inode *)inode); + struct inode *inode = arg; + sync_blockdev(mp->m_super->s_bdev); + iput(inode); } void @@ -531,35 +526,33 @@ xfs_flush_device( xfs_inode_t *ip) { struct inode *inode = vn_to_inode(XFS_ITOV(ip)); - struct bhv_vfs *vfs = XFS_MTOVFS(ip->i_mount); igrab(inode); - xfs_syncd_queue_work(vfs, inode, xfs_flush_device_work); + xfs_syncd_queue_work(ip->i_mount, inode, xfs_flush_device_work); delay(msecs_to_jiffies(500)); xfs_log_force(ip->i_mount, (xfs_lsn_t)0, XFS_LOG_FORCE|XFS_LOG_SYNC); } STATIC void -vfs_sync_worker( - bhv_vfs_t *vfsp, +xfs_sync_worker( + struct xfs_mount *mp, void *unused) { int error; - if (!(vfsp->vfs_flag & VFS_RDONLY)) - error = bhv_vfs_sync(vfsp, SYNC_FSDATA | SYNC_BDFLUSH | \ - SYNC_ATTR | SYNC_REFCACHE | SYNC_SUPER, - NULL); - vfsp->vfs_sync_seq++; - wake_up(&vfsp->vfs_wait_single_sync_task); + if (!(mp->m_flags & XFS_MOUNT_RDONLY)) + error = xfs_sync(mp, SYNC_FSDATA | SYNC_BDFLUSH | SYNC_ATTR | + SYNC_REFCACHE | SYNC_SUPER); + mp->m_sync_seq++; + wake_up(&mp->m_wait_single_sync_task); } STATIC int xfssyncd( void *arg) { + struct xfs_mount *mp = arg; long timeleft; - bhv_vfs_t *vfsp = (bhv_vfs_t *) arg; bhv_vfs_sync_work_t *work, *n; LIST_HEAD (tmp); @@ -569,31 +562,31 @@ xfssyncd( timeleft = schedule_timeout_interruptible(timeleft); /* swsusp */ try_to_freeze(); - if (kthread_should_stop() && list_empty(&vfsp->vfs_sync_list)) + if (kthread_should_stop() && list_empty(&mp->m_sync_list)) break; - spin_lock(&vfsp->vfs_sync_lock); + spin_lock(&mp->m_sync_lock); /* * We can get woken by laptop mode, to do a sync - * that's the (only!) case where the list would be * empty with time remaining. */ - if (!timeleft || list_empty(&vfsp->vfs_sync_list)) { + if (!timeleft || list_empty(&mp->m_sync_list)) { if (!timeleft) timeleft = xfs_syncd_centisecs * msecs_to_jiffies(10); - INIT_LIST_HEAD(&vfsp->vfs_sync_work.w_list); - list_add_tail(&vfsp->vfs_sync_work.w_list, - &vfsp->vfs_sync_list); + INIT_LIST_HEAD(&mp->m_sync_work.w_list); + list_add_tail(&mp->m_sync_work.w_list, + &mp->m_sync_list); } - list_for_each_entry_safe(work, n, &vfsp->vfs_sync_list, w_list) + list_for_each_entry_safe(work, n, &mp->m_sync_list, w_list) list_move(&work->w_list, &tmp); - spin_unlock(&vfsp->vfs_sync_lock); + spin_unlock(&mp->m_sync_lock); list_for_each_entry_safe(work, n, &tmp, w_list) { - (*work->w_syncer)(vfsp, work->w_data); + (*work->w_syncer)(mp, work->w_data); list_del(&work->w_list); - if (work == &vfsp->vfs_sync_work) + if (work == &mp->m_sync_work) continue; kmem_free(work, sizeof(struct bhv_vfs_sync_work)); } @@ -602,41 +595,19 @@ xfssyncd( return 0; } -STATIC int -xfs_fs_start_syncd( - bhv_vfs_t *vfsp) -{ - vfsp->vfs_sync_work.w_syncer = vfs_sync_worker; - vfsp->vfs_sync_work.w_vfs = vfsp; - vfsp->vfs_sync_task = kthread_run(xfssyncd, vfsp, "xfssyncd"); - if (IS_ERR(vfsp->vfs_sync_task)) - return -PTR_ERR(vfsp->vfs_sync_task); - return 0; -} - -STATIC void -xfs_fs_stop_syncd( - bhv_vfs_t *vfsp) -{ - kthread_stop(vfsp->vfs_sync_task); -} - STATIC void xfs_fs_put_super( struct super_block *sb) { - bhv_vfs_t *vfsp = vfs_from_sb(sb); + struct xfs_mount *mp = XFS_M(sb); int error; - xfs_fs_stop_syncd(vfsp); - bhv_vfs_sync(vfsp, SYNC_ATTR | SYNC_DELWRI, NULL); - error = bhv_vfs_unmount(vfsp, 0, NULL); - if (error) { + kthread_stop(mp->m_sync_task); + + xfs_sync(mp, SYNC_ATTR | SYNC_DELWRI); + error = xfs_unmount(mp, 0, NULL); + if (error) printk("XFS: unmount got error=%d\n", error); - printk("%s: vfs=0x%p left dangling!\n", __FUNCTION__, vfsp); - } else { - vfs_deallocate(vfsp); - } } STATIC void @@ -644,7 +615,7 @@ xfs_fs_write_super( struct super_block *sb) { if (!(sb->s_flags & MS_RDONLY)) - bhv_vfs_sync(vfs_from_sb(sb), SYNC_FSDATA, NULL); + xfs_sync(XFS_M(sb), SYNC_FSDATA); sb->s_dirt = 0; } @@ -653,11 +624,23 @@ xfs_fs_sync_super( struct super_block *sb, int wait) { - bhv_vfs_t *vfsp = vfs_from_sb(sb); + struct xfs_mount *mp = XFS_M(sb); int error; int flags; - if (unlikely(sb->s_frozen == SB_FREEZE_WRITE)) { + /* + * Treat a sync operation like a freeze. This is to work + * around a race in sync_inodes() which works in two phases + * - an asynchronous flush, which can write out an inode + * without waiting for file size updates to complete, and a + * synchronous flush, which wont do anything because the + * async flush removed the inode's dirty flag. Also + * sync_inodes() will not see any files that just have + * outstanding transactions to be flushed because we don't + * dirty the Linux inode until after the transaction I/O + * completes. + */ + if (wait || unlikely(sb->s_frozen == SB_FREEZE_WRITE)) { /* * First stage of freeze - no more writers will make progress * now we are here, so we flush delwri and delalloc buffers @@ -668,28 +651,28 @@ xfs_fs_sync_super( */ flags = SYNC_DATA_QUIESCE; } else - flags = SYNC_FSDATA | (wait ? SYNC_WAIT : 0); + flags = SYNC_FSDATA; - error = bhv_vfs_sync(vfsp, flags, NULL); + error = xfs_sync(mp, flags); sb->s_dirt = 0; if (unlikely(laptop_mode)) { - int prev_sync_seq = vfsp->vfs_sync_seq; + int prev_sync_seq = mp->m_sync_seq; /* * The disk must be active because we're syncing. * We schedule xfssyncd now (now that the disk is * active) instead of later (when it might not be). */ - wake_up_process(vfsp->vfs_sync_task); + wake_up_process(mp->m_sync_task); /* * We have to wait for the sync iteration to complete. * If we don't, the disk activity caused by the sync * will come after the sync is completed, and that * triggers another sync from laptop mode. */ - wait_event(vfsp->vfs_wait_single_sync_task, - vfsp->vfs_sync_seq != prev_sync_seq); + wait_event(mp->m_wait_single_sync_task, + mp->m_sync_seq != prev_sync_seq); } return -error; @@ -700,7 +683,7 @@ xfs_fs_statfs( struct dentry *dentry, struct kstatfs *statp) { - return -bhv_vfs_statvfs(vfs_from_sb(dentry->d_sb), statp, + return -xfs_statvfs(XFS_M(dentry->d_sb), statp, vn_from_inode(dentry->d_inode)); } @@ -710,13 +693,13 @@ xfs_fs_remount( int *flags, char *options) { - bhv_vfs_t *vfsp = vfs_from_sb(sb); + struct xfs_mount *mp = XFS_M(sb); struct xfs_mount_args *args = xfs_args_allocate(sb, 0); int error; - error = bhv_vfs_parseargs(vfsp, options, args, 1); + error = xfs_parseargs(mp, options, args, 1); if (!error) - error = bhv_vfs_mntupdate(vfsp, flags, args); + error = xfs_mntupdate(mp, flags, args); kmem_free(args, sizeof(*args)); return -error; } @@ -725,7 +708,7 @@ STATIC void xfs_fs_lockfs( struct super_block *sb) { - bhv_vfs_freeze(vfs_from_sb(sb)); + xfs_freeze(XFS_M(sb)); } STATIC int @@ -733,7 +716,7 @@ xfs_fs_show_options( struct seq_file *m, struct vfsmount *mnt) { - return -bhv_vfs_showargs(vfs_from_sb(mnt->mnt_sb), m); + return -xfs_showargs(XFS_M(mnt->mnt_sb), m); } STATIC int @@ -741,7 +724,7 @@ xfs_fs_quotasync( struct super_block *sb, int type) { - return -bhv_vfs_quotactl(vfs_from_sb(sb), Q_XQUOTASYNC, 0, NULL); + return -XFS_QM_QUOTACTL(XFS_M(sb), Q_XQUOTASYNC, 0, NULL); } STATIC int @@ -749,7 +732,7 @@ xfs_fs_getxstate( struct super_block *sb, struct fs_quota_stat *fqs) { - return -bhv_vfs_quotactl(vfs_from_sb(sb), Q_XGETQSTAT, 0, (caddr_t)fqs); + return -XFS_QM_QUOTACTL(XFS_M(sb), Q_XGETQSTAT, 0, (caddr_t)fqs); } STATIC int @@ -758,7 +741,7 @@ xfs_fs_setxstate( unsigned int flags, int op) { - return -bhv_vfs_quotactl(vfs_from_sb(sb), op, 0, (caddr_t)&flags); + return -XFS_QM_QUOTACTL(XFS_M(sb), op, 0, (caddr_t)&flags); } STATIC int @@ -768,7 +751,7 @@ xfs_fs_getxquota( qid_t id, struct fs_disk_quota *fdq) { - return -bhv_vfs_quotactl(vfs_from_sb(sb), + return -XFS_QM_QUOTACTL(XFS_M(sb), (type == USRQUOTA) ? Q_XGETQUOTA : ((type == GRPQUOTA) ? Q_XGETGQUOTA : Q_XGETPQUOTA), id, (caddr_t)fdq); @@ -781,7 +764,7 @@ xfs_fs_setxquota( qid_t id, struct fs_disk_quota *fdq) { - return -bhv_vfs_quotactl(vfs_from_sb(sb), + return -XFS_QM_QUOTACTL(XFS_M(sb), (type == USRQUOTA) ? Q_XSETQLIM : ((type == GRPQUOTA) ? Q_XSETGQLIM : Q_XSETPQLIM), id, (caddr_t)fdq); @@ -793,32 +776,38 @@ xfs_fs_fill_super( void *data, int silent) { - struct bhv_vnode *rootvp; - struct bhv_vfs *vfsp = vfs_allocate(sb); + struct inode *rootvp; + struct xfs_mount *mp = NULL; struct xfs_mount_args *args = xfs_args_allocate(sb, silent); struct kstatfs statvfs; int error; - bhv_insert_all_vfsops(vfsp); + mp = xfs_mount_init(); - error = bhv_vfs_parseargs(vfsp, (char *)data, args, 0); - if (error) { - bhv_remove_all_vfsops(vfsp, 1); + INIT_LIST_HEAD(&mp->m_sync_list); + spin_lock_init(&mp->m_sync_lock); + init_waitqueue_head(&mp->m_wait_single_sync_task); + + mp->m_super = sb; + sb->s_fs_info = mp; + + if (sb->s_flags & MS_RDONLY) + mp->m_flags |= XFS_MOUNT_RDONLY; + + error = xfs_parseargs(mp, (char *)data, args, 0); + if (error) goto fail_vfsop; - } sb_min_blocksize(sb, BBSIZE); sb->s_export_op = &xfs_export_operations; sb->s_qcop = &xfs_quotactl_operations; sb->s_op = &xfs_super_operations; - error = bhv_vfs_mount(vfsp, args, NULL); - if (error) { - bhv_remove_all_vfsops(vfsp, 1); + error = xfs_mount(mp, args, NULL); + if (error) goto fail_vfsop; - } - error = bhv_vfs_statvfs(vfsp, &statvfs, NULL); + error = xfs_statvfs(mp, &statvfs, NULL); if (error) goto fail_unmount; @@ -830,7 +819,7 @@ xfs_fs_fill_super( sb->s_time_gran = 1; set_posix_acl_flag(sb); - error = bhv_vfs_root(vfsp, &rootvp); + error = xfs_root(mp, &rootvp); if (error) goto fail_unmount; @@ -843,9 +832,17 @@ xfs_fs_fill_super( error = EINVAL; goto fail_vnrele; } - if ((error = xfs_fs_start_syncd(vfsp))) + + mp->m_sync_work.w_syncer = xfs_sync_worker; + mp->m_sync_work.w_mount = mp; + mp->m_sync_task = kthread_run(xfssyncd, mp, "xfssyncd"); + if (IS_ERR(mp->m_sync_task)) { + error = -PTR_ERR(mp->m_sync_task); goto fail_vnrele; - vn_trace_exit(rootvp, __FUNCTION__, (inst_t *)__return_address); + } + + vn_trace_exit(XFS_I(sb->s_root->d_inode), __FUNCTION__, + (inst_t *)__return_address); kmem_free(args, sizeof(*args)); return 0; @@ -859,10 +856,9 @@ 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(); diff --git a/fs/xfs/linux-2.6/xfs_super.h b/fs/xfs/linux-2.6/xfs_super.h index 201cc3273c84..c78c23310fe8 100644 --- a/fs/xfs/linux-2.6/xfs_super.h +++ b/fs/xfs/linux-2.6/xfs_super.h @@ -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__ */ diff --git a/fs/xfs/linux-2.6/xfs_vfs.c b/fs/xfs/linux-2.6/xfs_vfs.c deleted file mode 100644 index 6145e8bd0be2..000000000000 --- a/fs/xfs/linux-2.6/xfs_vfs.c +++ /dev/null @@ -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); -} diff --git a/fs/xfs/linux-2.6/xfs_vfs.h b/fs/xfs/linux-2.6/xfs_vfs.h index dca3481aaafa..4da03a4e3520 100644 --- a/fs/xfs/linux-2.6/xfs_vfs.h +++ b/fs/xfs/linux-2.6/xfs_vfs.h @@ -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__ */ diff --git a/fs/xfs/linux-2.6/xfs_vnode.c b/fs/xfs/linux-2.6/xfs_vnode.c index ada24baf88de..814169fd7e1e 100644 --- a/fs/xfs/linux-2.6/xfs_vnode.c +++ b/fs/xfs/linux-2.6/xfs_vnode.c @@ -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 */ diff --git a/fs/xfs/linux-2.6/xfs_vnode.h b/fs/xfs/linux-2.6/xfs_vnode.h index 5742d65f0785..55fb46948589 100644 --- a/fs/xfs/linux-2.6/xfs_vnode.h +++ b/fs/xfs/linux-2.6/xfs_vnode.h @@ -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,7 +58,7 @@ 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. */ @@ -119,193 +66,6 @@ typedef enum bhv_vrwlock { #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 */ #define IO_ISAIO 0x00001 /* don't wait for completion */ @@ -428,16 +188,19 @@ typedef struct bhv_vattr { extern void vn_init(void); extern bhv_vnode_t *vn_initialize(struct inode *); -extern int vn_revalidate(struct bhv_vnode *); -extern int __vn_revalidate(struct bhv_vnode *, bhv_vattr_t *); -extern void vn_revalidate_core(struct bhv_vnode *, bhv_vattr_t *); - -extern void vn_iowait(struct bhv_vnode *vp); -extern void vn_iowake(struct bhv_vnode *vp); +extern int vn_revalidate(bhv_vnode_t *); +extern int __vn_revalidate(bhv_vnode_t *, bhv_vattr_t *); +extern void vn_revalidate_core(bhv_vnode_t *, bhv_vattr_t *); -extern void vn_ioerror(struct bhv_vnode *vp, int error, char *f, int l); +/* + * Yeah, these don't take vnode anymore at all, all this should be + * cleaned up at some point. + */ +extern void vn_iowait(struct xfs_inode *ip); +extern void vn_iowake(struct xfs_inode *ip); +extern void vn_ioerror(struct xfs_inode *ip, int error, char *f, int l); -static inline int vn_count(struct bhv_vnode *vp) +static inline int vn_count(bhv_vnode_t *vp) { return atomic_read(&vn_to_inode(vp)->i_count); } @@ -445,21 +208,21 @@ static inline int vn_count(struct bhv_vnode *vp) /* * Vnode reference counting functions (and macros for compatibility). */ -extern bhv_vnode_t *vn_hold(struct bhv_vnode *); +extern bhv_vnode_t *vn_hold(bhv_vnode_t *); #if defined(XFS_VNODE_TRACE) #define VN_HOLD(vp) \ ((void)vn_hold(vp), \ - vn_trace_hold(vp, __FILE__, __LINE__, (inst_t *)__return_address)) + vn_trace_hold(xfs_vtoi(vp), __FILE__, __LINE__, (inst_t *)__return_address)) #define VN_RELE(vp) \ - (vn_trace_rele(vp, __FILE__, __LINE__, (inst_t *)__return_address), \ + (vn_trace_rele(xfs_vtoi(vp), __FILE__, __LINE__, (inst_t *)__return_address), \ iput(vn_to_inode(vp))) #else #define VN_HOLD(vp) ((void)vn_hold(vp)) #define VN_RELE(vp) (iput(vn_to_inode(vp))) #endif -static inline struct bhv_vnode *vn_grab(struct bhv_vnode *vp) +static inline bhv_vnode_t *vn_grab(bhv_vnode_t *vp) { struct inode *inode = igrab(vn_to_inode(vp)); return inode ? vn_from_inode(inode) : NULL; @@ -473,43 +236,14 @@ static inline struct bhv_vnode *vn_grab(struct bhv_vnode *vp) #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__ */ diff --git a/fs/xfs/quota/xfs_qm.c b/fs/xfs/quota/xfs_qm.c index 6ff0f4de1630..b5f91281b707 100644 --- a/fs/xfs/quota/xfs_qm.c +++ b/fs/xfs/quota/xfs_qm.c @@ -288,45 +288,6 @@ xfs_qm_rele_quotafs_ref( } /* - * 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. */ void @@ -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; /* diff --git a/fs/xfs/quota/xfs_qm.h b/fs/xfs/quota/xfs_qm.h index 689407de0a20..23ccaa5fceaf 100644 --- a/fs/xfs/quota/xfs_qm.h +++ b/fs/xfs/quota/xfs_qm.h @@ -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 *); diff --git a/fs/xfs/quota/xfs_qm_bhv.c b/fs/xfs/quota/xfs_qm_bhv.c index d2cdb8a2aad6..97bb32937585 100644 --- a/fs/xfs/quota/xfs_qm_bhv.c +++ b/fs/xfs/quota/xfs_qm_bhv.c @@ -48,172 +48,13 @@ #include "xfs_buf_item.h" #include "xfs_qm.h" -#define MNTOPT_QUOTA "quota" /* disk quotas (user) */ -#define MNTOPT_NOQUOTA "noquota" /* no quotas */ -#define MNTOPT_USRQUOTA "usrquota" /* user quota enabled */ -#define MNTOPT_GRPQUOTA "grpquota" /* group quota enabled */ -#define MNTOPT_PRJQUOTA "prjquota" /* project quota enabled */ -#define MNTOPT_UQUOTA "uquota" /* user quota (IRIX variant) */ -#define MNTOPT_GQUOTA "gquota" /* group quota (IRIX variant) */ -#define MNTOPT_PQUOTA "pquota" /* project quota (IRIX variant) */ -#define MNTOPT_UQUOTANOENF "uqnoenforce"/* user quota limit enforcement */ -#define MNTOPT_GQUOTANOENF "gqnoenforce"/* group quota limit enforcement */ -#define MNTOPT_PQUOTANOENF "pqnoenforce"/* project quota limit enforcement */ -#define MNTOPT_QUOTANOENF "qnoenforce" /* same as uqnoenforce */ -STATIC int -xfs_qm_parseargs( - struct bhv_desc *bhv, - char *options, - struct xfs_mount_args *args, - int update) -{ - size_t length; - char *local_options = options; - char *this_char; - int error; - int referenced = update; - - while ((this_char = strsep(&local_options, ",")) != NULL) { - length = strlen(this_char); - if (local_options) - length++; - - if (!strcmp(this_char, MNTOPT_NOQUOTA)) { - args->flags &= ~(XFSMNT_UQUOTAENF|XFSMNT_UQUOTA); - args->flags &= ~(XFSMNT_GQUOTAENF|XFSMNT_GQUOTA); - referenced = update; - } else if (!strcmp(this_char, MNTOPT_QUOTA) || - !strcmp(this_char, MNTOPT_UQUOTA) || - !strcmp(this_char, MNTOPT_USRQUOTA)) { - args->flags |= XFSMNT_UQUOTA | XFSMNT_UQUOTAENF; - referenced = 1; - } else if (!strcmp(this_char, MNTOPT_QUOTANOENF) || - !strcmp(this_char, MNTOPT_UQUOTANOENF)) { - args->flags |= XFSMNT_UQUOTA; - args->flags &= ~XFSMNT_UQUOTAENF; - referenced = 1; - } else if (!strcmp(this_char, MNTOPT_PQUOTA) || - !strcmp(this_char, MNTOPT_PRJQUOTA)) { - args->flags |= XFSMNT_PQUOTA | XFSMNT_PQUOTAENF; - referenced = 1; - } else if (!strcmp(this_char, MNTOPT_PQUOTANOENF)) { - args->flags |= XFSMNT_PQUOTA; - args->flags &= ~XFSMNT_PQUOTAENF; - referenced = 1; - } else if (!strcmp(this_char, MNTOPT_GQUOTA) || - !strcmp(this_char, MNTOPT_GRPQUOTA)) { - args->flags |= XFSMNT_GQUOTA | XFSMNT_GQUOTAENF; - referenced = 1; - } else if (!strcmp(this_char, MNTOPT_GQUOTANOENF)) { - args->flags |= XFSMNT_GQUOTA; - args->flags &= ~XFSMNT_GQUOTAENF; - referenced = 1; - } else { - if (local_options) - *(local_options-1) = ','; - continue; - } - - while (length--) - *this_char++ = ','; - } - - if ((args->flags & XFSMNT_GQUOTA) && (args->flags & XFSMNT_PQUOTA)) { - cmn_err(CE_WARN, - "XFS: cannot mount with both project and group quota"); - return XFS_ERROR(EINVAL); - } - - error = bhv_next_vfs_parseargs(BHV_NEXT(bhv), options, args, update); - if (!error && !referenced) - bhv_remove_vfsops(bhvtovfs(bhv), VFS_POSITION_QM); - return error; -} - -STATIC int -xfs_qm_showargs( - struct bhv_desc *bhv, - struct seq_file *m) -{ - struct bhv_vfs *vfsp = bhvtovfs(bhv); - struct xfs_mount *mp = XFS_VFSTOM(vfsp); - - if (mp->m_qflags & XFS_UQUOTA_ACCT) { - (mp->m_qflags & XFS_UQUOTA_ENFD) ? - seq_puts(m, "," MNTOPT_USRQUOTA) : - seq_puts(m, "," MNTOPT_UQUOTANOENF); - } - - if (mp->m_qflags & XFS_PQUOTA_ACCT) { - (mp->m_qflags & XFS_OQUOTA_ENFD) ? - seq_puts(m, "," MNTOPT_PRJQUOTA) : - seq_puts(m, "," MNTOPT_PQUOTANOENF); - } - - if (mp->m_qflags & XFS_GQUOTA_ACCT) { - (mp->m_qflags & XFS_OQUOTA_ENFD) ? - seq_puts(m, "," MNTOPT_GRPQUOTA) : - seq_puts(m, "," MNTOPT_GQUOTANOENF); - } - - if (!(mp->m_qflags & XFS_ALL_QUOTA_ACCT)) - seq_puts(m, "," MNTOPT_NOQUOTA); - - return bhv_next_vfs_showargs(BHV_NEXT(bhv), m); -} - -STATIC int -xfs_qm_mount( - struct bhv_desc *bhv, - struct xfs_mount_args *args, - struct cred *cr) -{ - struct bhv_vfs *vfsp = bhvtovfs(bhv); - struct xfs_mount *mp = XFS_VFSTOM(vfsp); - - if (args->flags & (XFSMNT_UQUOTA | XFSMNT_GQUOTA | XFSMNT_PQUOTA)) - xfs_qm_mount_quotainit(mp, args->flags); - return bhv_next_vfs_mount(BHV_NEXT(bhv), args, cr); -} - -/* - * Directory tree accounting is implemented using project quotas, where - * the project identifier is inherited from parent directories. - * A statvfs (df, etc.) of a directory that is using project quota should - * return a statvfs of the project, not the entire filesystem. - * This makes such trees appear as if they are filesystems in themselves. - */ -STATIC int -xfs_qm_statvfs( - struct bhv_desc *bhv, +STATIC void +xfs_fill_statvfs_from_dquot( bhv_statvfs_t *statp, - struct bhv_vnode *vnode) + xfs_disk_dquot_t *dp) { - xfs_mount_t *mp; - xfs_inode_t *ip; - xfs_dquot_t *dqp; - xfs_disk_dquot_t *dp; __uint64_t limit; - int error; - - error = bhv_next_vfs_statvfs(BHV_NEXT(bhv), statp, vnode); - if (error || !vnode) - return error; - - mp = xfs_vfstom(bhvtovfs(bhv)); - ip = xfs_vtoi(vnode); - - if (!(ip->i_d.di_flags & XFS_DIFLAG_PROJINHERIT)) - return 0; - if (!(mp->m_qflags & XFS_PQUOTA_ACCT)) - return 0; - if (!(mp->m_qflags & XFS_OQUOTA_ENFD)) - return 0; - - if (xfs_qm_dqget(mp, NULL, ip->i_d.di_projid, XFS_DQ_PROJ, 0, &dqp)) - return 0; - dp = &dqp->q_core; limit = dp->d_blk_softlimit ? be64_to_cpu(dp->d_blk_softlimit) : @@ -234,37 +75,35 @@ xfs_qm_statvfs( (statp->f_files > be64_to_cpu(dp->d_icount)) ? (statp->f_ffree - be64_to_cpu(dp->d_icount)) : 0; } - - xfs_qm_dqput(dqp); - return 0; } -STATIC int -xfs_qm_syncall( - struct bhv_desc *bhv, - int flags, - cred_t *credp) + +/* + * Directory tree accounting is implemented using project quotas, where + * the project identifier is inherited from parent directories. + * A statvfs (df, etc.) of a directory that is using project quota should + * return a statvfs of the project, not the entire filesystem. + * This makes such trees appear as if they are filesystems in themselves. + */ +STATIC void +xfs_qm_statvfs( + xfs_inode_t *ip, + bhv_statvfs_t *statp) { - struct bhv_vfs *vfsp = bhvtovfs(bhv); - struct xfs_mount *mp = XFS_VFSTOM(vfsp); - int error; + xfs_mount_t *mp = ip->i_mount; + xfs_dquot_t *dqp; - /* - * Get the Quota Manager to flush the dquots. - */ - if (XFS_IS_QUOTA_ON(mp)) { - if ((error = xfs_qm_sync(mp, flags))) { - /* - * If we got an IO error, we will be shutting down. - * So, there's nothing more for us to do here. - */ - ASSERT(error != EIO || XFS_FORCED_SHUTDOWN(mp)); - if (XFS_FORCED_SHUTDOWN(mp)) { - return XFS_ERROR(error); - } - } + if (!(ip->i_d.di_flags & XFS_DIFLAG_PROJINHERIT) || + !((mp->m_qflags & (XFS_PQUOTA_ACCT|XFS_OQUOTA_ENFD))) == + (XFS_PQUOTA_ACCT|XFS_OQUOTA_ENFD)) + return; + + if (!xfs_qm_dqget(mp, NULL, ip->i_d.di_projid, XFS_DQ_PROJ, 0, &dqp)) { + xfs_disk_dquot_t *dp = &dqp->q_core; + + xfs_fill_statvfs_from_dquot(statp, dp); + xfs_qm_dqput(dqp); } - return bhv_next_vfs_sync(BHV_NEXT(bhv), flags, credp); } STATIC int @@ -382,7 +221,7 @@ xfs_qm_dqrele_null( } -static struct xfs_qmops xfs_qmcore_xfs = { +struct xfs_qmops xfs_qmcore_xfs = { .xfs_qminit = xfs_qm_newmount, .xfs_qmdone = xfs_qm_unmount_quotadestroy, .xfs_qmmount = xfs_qm_endmount, @@ -396,36 +235,24 @@ static struct xfs_qmops xfs_qmcore_xfs = { .xfs_dqvoprename = xfs_qm_vop_rename_dqattach, .xfs_dqvopchown = xfs_qm_vop_chown, .xfs_dqvopchownresv = xfs_qm_vop_chown_reserve, + .xfs_dqstatvfs = xfs_qm_statvfs, + .xfs_dqsync = xfs_qm_sync, + .xfs_quotactl = xfs_qm_quotactl, .xfs_dqtrxops = &xfs_trans_dquot_ops, }; - -struct bhv_module_vfsops xfs_qmops = { { - BHV_IDENTITY_INIT(VFS_BHV_QM, VFS_POSITION_QM), - .vfs_parseargs = xfs_qm_parseargs, - .vfs_showargs = xfs_qm_showargs, - .vfs_mount = xfs_qm_mount, - .vfs_statvfs = xfs_qm_statvfs, - .vfs_sync = xfs_qm_syncall, - .vfs_quotactl = xfs_qm_quotactl, }, -}; - +EXPORT_SYMBOL(xfs_qmcore_xfs); void __init xfs_qm_init(void) { - static char message[] __initdata = - KERN_INFO "SGI XFS Quota Management subsystem\n"; - - printk(message); + printk(KERN_INFO "SGI XFS Quota Management subsystem\n"); mutex_init(&xfs_Gqm_lock); - vfs_bhv_set_custom(&xfs_qmops, &xfs_qmcore_xfs); xfs_qm_init_procfs(); } void __exit xfs_qm_exit(void) { - vfs_bhv_clr_custom(&xfs_qmops); xfs_qm_cleanup_procfs(); if (qm_dqzone) kmem_zone_destroy(qm_dqzone); diff --git a/fs/xfs/quota/xfs_qm_syscalls.c b/fs/xfs/quota/xfs_qm_syscalls.c index 2df67fd913e5..ad5579d4eac4 100644 --- a/fs/xfs/quota/xfs_qm_syscalls.c +++ b/fs/xfs/quota/xfs_qm_syscalls.c @@ -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); diff --git a/fs/xfs/support/move.c b/fs/xfs/support/move.c deleted file mode 100644 index ac8617ca3909..000000000000 --- a/fs/xfs/support/move.c +++ /dev/null @@ -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; -} diff --git a/fs/xfs/support/move.h b/fs/xfs/support/move.h deleted file mode 100644 index 324e413deadd..000000000000 --- a/fs/xfs/support/move.h +++ /dev/null @@ -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__ */ diff --git a/fs/xfs/xfs_acl.c b/fs/xfs/xfs_acl.c index 4ca4beb7bb54..5bfb66f33caf 100644 --- a/fs/xfs/xfs_acl.c +++ b/fs/xfs/xfs_acl.c @@ -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); } /* diff --git a/fs/xfs/xfs_acl.h b/fs/xfs/xfs_acl.h index f853cf1a6270..34b7d3391299 100644 --- a/fs/xfs/xfs_acl.h +++ b/fs/xfs/xfs_acl.h @@ -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) diff --git a/fs/xfs/xfs_ag.h b/fs/xfs/xfs_ag.h index 51c09c114a20..9381b0360c4b 100644 --- a/fs/xfs/xfs_ag.h +++ b/fs/xfs/xfs_ag.h @@ -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) diff --git a/fs/xfs/xfs_attr.c b/fs/xfs/xfs_attr.c index 7ce44a7b88a2..93fa64dd1be6 100644 --- a/fs/xfs/xfs_attr.c +++ b/fs/xfs/xfs_attr.c @@ -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; diff --git a/fs/xfs/xfs_attr.h b/fs/xfs/xfs_attr.h index 783977d3ea71..786eba3121c4 100644 --- a/fs/xfs/xfs_attr.h +++ b/fs/xfs/xfs_attr.h @@ -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); diff --git a/fs/xfs/xfs_behavior.c b/fs/xfs/xfs_behavior.c deleted file mode 100644 index 0dc17219d412..000000000000 --- a/fs/xfs/xfs_behavior.c +++ /dev/null @@ -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); -} diff --git a/fs/xfs/xfs_behavior.h b/fs/xfs/xfs_behavior.h deleted file mode 100644 index e7ca1fed955a..000000000000 --- a/fs/xfs/xfs_behavior.h +++ /dev/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__ */ diff --git a/fs/xfs/xfs_bmap.c b/fs/xfs/xfs_bmap.c index 94b5c5fe2681..2e9b34b7344b 100644 --- a/fs/xfs/xfs_bmap.c +++ b/fs/xfs/xfs_bmap.c @@ -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 */ @@ -273,21 +274,6 @@ xfs_bmap_isaeof( #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. */ STATIC void @@ -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 */ @@ -5743,11 +5728,44 @@ error0: } /* + * 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; diff --git a/fs/xfs/xfs_bmap.h b/fs/xfs/xfs_bmap.h index 524b1c9d5246..68267d75ff19 100644 --- a/fs/xfs/xfs_bmap.h +++ b/fs/xfs/xfs_bmap.h @@ -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 *); diff --git a/fs/xfs/xfs_bmap_btree.c b/fs/xfs/xfs_bmap_btree.c index 89b891f51cfb..32b49ec00fb5 100644 --- a/fs/xfs/xfs_bmap_btree.c +++ b/fs/xfs/xfs_bmap_btree.c @@ -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. @@ -2290,185 +2283,131 @@ xfs_bmbt_newroot( } /* - * 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_disk_set_all( - xfs_bmbt_rec_t *r, - xfs_bmbt_irec_t *s) +xfs_bmbt_set_all( + xfs_bmbt_rec_host_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_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) + xfs_bmbt_rec_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); - 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))); + 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(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 & + 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 { - 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))); + 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 */ } -#endif /* XFS_NATIVE_HOST */ + +/* + * Set all the fields in a bmap extent record from the uncompressed form. + */ +void +xfs_bmbt_disk_set_all( + xfs_bmbt_rec_t *r, + xfs_bmbt_irec_t *s) +{ + xfs_bmbt_disk_set_allf(r, s->br_startoff, s->br_startblock, + s->br_blockcount, s->br_state); +} /* * 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); diff --git a/fs/xfs/xfs_bmap_btree.h b/fs/xfs/xfs_bmap_btree.h index a77b1b753d0c..2d950e975918 100644 --- a/fs/xfs/xfs_bmap_btree.h +++ b/fs/xfs/xfs_bmap_btree.h @@ -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, diff --git a/fs/xfs/xfs_buf_item.c b/fs/xfs/xfs_buf_item.c index b0667cb27d66..c8f2c2886fe4 100644 --- a/fs/xfs/xfs_buf_item.c +++ b/fs/xfs/xfs_buf_item.c @@ -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" diff --git a/fs/xfs/xfs_clnt.h b/fs/xfs/xfs_clnt.h index f89196cb08d2..d16c1b971074 100644 --- a/fs/xfs/xfs_clnt.h +++ b/fs/xfs/xfs_clnt.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 */ diff --git a/fs/xfs/xfs_dfrag.c b/fs/xfs/xfs_dfrag.c index de35d18cc002..584f1ae85cd9 100644 --- a/fs/xfs/xfs_dfrag.c +++ b/fs/xfs/xfs_dfrag.c @@ -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, diff --git a/fs/xfs/xfs_dinode.h b/fs/xfs/xfs_dinode.h index fefd0116bac9..dedd713574e1 100644 --- a/fs/xfs/xfs_dinode.h +++ b/fs/xfs/xfs_dinode.h @@ -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) diff --git a/fs/xfs/xfs_dir2.c b/fs/xfs/xfs_dir2.c index 29e091914df4..b0f1ee8fcb90 100644 --- a/fs/xfs/xfs_dir2.c +++ b/fs/xfs/xfs_dir2.c @@ -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; } @@ -613,77 +597,6 @@ xfs_dir2_isleaf( } /* - * 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 * by xfs_da_shrink_inode. diff --git a/fs/xfs/xfs_dir2.h b/fs/xfs/xfs_dir2.h index 86560b6f794c..b265197e74cf 100644 --- a/fs/xfs/xfs_dir2.h +++ b/fs/xfs/xfs_dir2.h @@ -60,21 +60,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 */ extern void xfs_dir_startup(void); @@ -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, diff --git a/fs/xfs/xfs_dir2_block.c b/fs/xfs/xfs_dir2_block.c index e4df1aaae2a2..c171767e242a 100644 --- a/fs/xfs/xfs_dir2_block.c +++ b/fs/xfs/xfs_dir2_block.c @@ -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; } diff --git a/fs/xfs/xfs_dir2_block.h b/fs/xfs/xfs_dir2_block.h index e7c2606161e9..10e689676382 100644 --- a/fs/xfs/xfs_dir2_block.h +++ b/fs/xfs/xfs_dir2_block.h @@ -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); diff --git a/fs/xfs/xfs_dir2_data.c b/fs/xfs/xfs_dir2_data.c index 7ebe295bd6d3..d2452699e9b1 100644 --- a/fs/xfs/xfs_dir2_data.c +++ b/fs/xfs/xfs_dir2_data.c @@ -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" diff --git a/fs/xfs/xfs_dir2_leaf.c b/fs/xfs/xfs_dir2_leaf.c index 1b73c9ad646a..e7c12fa1303e 100644 --- a/fs/xfs/xfs_dir2_leaf.c +++ b/fs/xfs/xfs_dir2_leaf.c @@ -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(p->namelen); - - p->cook = xfs_dir2_byte_to_dataptr(mp, curoff + length); + length = xfs_dir2_data_entsize(dep->namelen); - 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; } diff --git a/fs/xfs/xfs_dir2_leaf.h b/fs/xfs/xfs_dir2_leaf.h index 70c97f3f815e..6c9539f06987 100644 --- a/fs/xfs/xfs_dir2_leaf.h +++ b/fs/xfs/xfs_dir2_leaf.h @@ -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, diff --git a/fs/xfs/xfs_dir2_node.c b/fs/xfs/xfs_dir2_node.c index 91c61d9632c8..eb18e399e836 100644 --- a/fs/xfs/xfs_dir2_node.c +++ b/fs/xfs/xfs_dir2_node.c @@ -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" diff --git a/fs/xfs/xfs_dir2_sf.c b/fs/xfs/xfs_dir2_sf.c index 38fc4f22b76d..182c70315ad1 100644 --- a/fs/xfs/xfs_dir2_sf.c +++ b/fs/xfs/xfs_dir2_sf.c @@ -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)); + ino = xfs_dir2_sf_get_inumber(sfp, xfs_dir2_sf_inumberp(sfep)); #if XFS_BIG_INUMS - p.ino += mp->m_inoadd; + ino += mp->m_inoadd; #endif - p.name = (char *)sfep->name; - - error = p.put(&p); - if (!p.done) { - uio->uio_offset = off; - return error; + 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; } diff --git a/fs/xfs/xfs_dir2_sf.h b/fs/xfs/xfs_dir2_sf.h index 11e503209afa..005629d702d2 100644 --- a/fs/xfs/xfs_dir2_sf.h +++ b/fs/xfs/xfs_dir2_sf.h @@ -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); diff --git a/fs/xfs/xfs_dmapi.h b/fs/xfs/xfs_dmapi.h index adc3d251240d..f71784ab6a60 100644 --- a/fs/xfs/xfs_dmapi.h +++ b/fs/xfs/xfs_dmapi.h @@ -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__ */ diff --git a/fs/xfs/xfs_dmops.c b/fs/xfs/xfs_dmops.c index 1e4a35ddf7f9..6cd5704258a2 100644 --- a/fs/xfs/xfs_dmops.c +++ b/fs/xfs/xfs_dmops.c @@ -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); +} diff --git a/fs/xfs/xfs_error.c b/fs/xfs/xfs_error.c index 8c4331631337..a4634d94e561 100644 --- a/fs/xfs/xfs_error.c +++ b/fs/xfs/xfs_error.c @@ -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 diff --git a/fs/xfs/xfs_error.h b/fs/xfs/xfs_error.h index 5599ada456a1..10e9d9619ae5 100644 --- a/fs/xfs/xfs_error.h +++ b/fs/xfs/xfs_error.h @@ -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) */ /* diff --git a/fs/xfs/xfs_extfree_item.c b/fs/xfs/xfs_extfree_item.c index 3b14427ee123..f938a51be81b 100644 --- a/fs/xfs/xfs_extfree_item.c +++ b/fs/xfs/xfs_extfree_item.c @@ -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" diff --git a/fs/xfs/xfs_fsops.c b/fs/xfs/xfs_fsops.c index 432e82347ed6..c92d5b821029 100644 --- a/fs/xfs/xfs_fsops.c +++ b/fs/xfs/xfs_fsops.c @@ -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); diff --git a/fs/xfs/xfs_ialloc.c b/fs/xfs/xfs_ialloc.c index f943368c9b93..1409c2d61c11 100644 --- a/fs/xfs/xfs_ialloc.c +++ b/fs/xfs/xfs_ialloc.c @@ -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); } diff --git a/fs/xfs/xfs_ialloc.h b/fs/xfs/xfs_ialloc.h index 97f4040931ca..4e30ec1d13bc 100644 --- a/fs/xfs/xfs_ialloc.h +++ b/fs/xfs/xfs_ialloc.h @@ -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 /* diff --git a/fs/xfs/xfs_iget.c b/fs/xfs/xfs_iget.c index 114433a22baa..488836e204a3 100644 --- a/fs/xfs/xfs_iget.c +++ b/fs/xfs/xfs_iget.c @@ -40,131 +40,13 @@ #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. - * - * 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(). + * 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 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; + + /* 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(&pag->pag_ici_lock); + ip = radix_tree_lookup(&pag->pag_ici_root, agino); - ih = XFS_IHASH(mp, 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); -again: - read_lock(&ih->ih_lock); + goto again; + } - for (ip = ih->ih_next; ip != NULL; ip = ip->i_next) { - if (ip->i_ino == ino) { + 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); + /* + * 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; + } + + /* + * 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(&pag->pag_ici_lock); + xfs_log_force(mp, 0, + XFS_LOG_FORCE|XFS_LOG_SYNC); + XFS_STATS_INC(xs_ig_frecycle); + goto again; + } - XFS_STATS_INC(xs_ig_found); + vn_trace_exit(ip, "xfs_iget.alloc", + (inst_t *)__return_address); - xfs_iflags_clear(ip, XFS_IRECLAIMABLE); - version = ih->ih_version; - read_unlock(&ih->ih_lock); - xfs_ihash_promote(ih, ip, version); + XFS_STATS_INC(xs_ig_found); - XFS_MOUNT_ILOCK(mp); - list_del_init(&ip->i_reclaim); - XFS_MOUNT_IUNLOCK(mp); + xfs_iflags_clear(ip, XFS_IRECLAIMABLE); + read_unlock(&pag->pag_ici_lock); - goto finish_inode; + XFS_MOUNT_ILOCK(mp); + list_del_init(&ip->i_reclaim); + XFS_MOUNT_IUNLOCK(mp); - } else if (vp != inode_vp) { - struct inode *inode = vn_to_inode(inode_vp); + goto finish_inode; - /* 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); + } else if (vp != inode_vp) { + struct inode *inode = vn_to_inode(inode_vp); - 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); + /* 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: 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. - */ - version = ih->ih_version; - read_unlock(&ih->ih_lock); - xfs_ihash_promote(ih, ip, version); - XFS_STATS_INC(xs_ig_found); + /* + * 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)) - return ENOENT; - xfs_iocore_inode_reinit(ip); + 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); + if (lock_flags != 0) + xfs_ilock(ip, lock_flags); - xfs_iflags_clear(ip, XFS_ISTALE); - vn_trace_exit(vp, "xfs_iget.found", - (inst_t *)__return_address); - goto return_ip; - } + 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); - - 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; - } - } + ASSERT(ip->i_cluster == NULL); - /* 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; - - 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); + xfs_perag_t *pag; + + 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); - - 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); + spin_lock(&ip->i_cluster->icl_lock); + hlist_del(&ip->i_cnode); + spin_unlock(&ip->i_cluster->icl_lock); + + /* 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. diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c index cdc4c28926d0..abf509a88915 100644 --- a/fs/xfs/xfs_inode.c +++ b/fs/xfs/xfs_inode.c @@ -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; - - 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); + 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); +} + +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 */ diff --git a/fs/xfs/xfs_inode.h b/fs/xfs/xfs_inode.h index 012dfd4a958c..e5aff929cc65 100644 --- a/fs/xfs/xfs_inode.h +++ b/fs/xfs/xfs_inode.h @@ -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. - */ -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. + * 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_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; diff --git a/fs/xfs/xfs_iocore.c b/fs/xfs/xfs_iocore.c index 81548ec72ba6..b27b5d5be841 100644 --- a/fs/xfs/xfs_iocore.c +++ b/fs/xfs/xfs_iocore.c @@ -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 = { diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c index bf57b75acb90..72786e356d56 100644 --- a/fs/xfs/xfs_iomap.c +++ b/fs/xfs/xfs_iomap.c @@ -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 */ diff --git a/fs/xfs/xfs_iomap.h b/fs/xfs/xfs_iomap.h index df441ee936b2..f5c09887fe93 100644 --- a/fs/xfs/xfs_iomap.h +++ b/fs/xfs/xfs_iomap.h @@ -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 */ diff --git a/fs/xfs/xfs_itable.c b/fs/xfs/xfs_itable.c index 4c2454bcc714..9972992fd3c3 100644 --- a/fs/xfs/xfs_itable.c +++ b/fs/xfs/xfs_itable.c @@ -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; } diff --git a/fs/xfs/xfs_log.c b/fs/xfs/xfs_log.c index 9bfb69e1e885..77c12715a7d0 100644 --- a/fs/xfs/xfs_log.c +++ b/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); @@ -949,6 +971,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. */ if (XFS_TEST_ERROR((XFS_BUF_GETERROR(bp)), l->l_mp, @@ -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 */ diff --git a/fs/xfs/xfs_log_priv.h b/fs/xfs/xfs_log_priv.h index 9bd3cdf11a87..752f964b3699 100644 --- a/fs/xfs/xfs_log_priv.h +++ b/fs/xfs/xfs_log_priv.h @@ -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 diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c index 8ae6e8e5f3db..851eca8a7150 100644 --- a/fs/xfs/xfs_log_recover.c +++ b/fs/xfs/xfs_log_recover.c @@ -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); diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c index a66b39805176..ebdb76da527c 100644 --- a/fs/xfs/xfs_mount.c +++ b/fs/xfs/xfs_mount.c @@ -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); @@ -1012,20 +1017,13 @@ 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. */ init_rwsem(&mp->m_peraglock); 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 */ diff --git a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h index 76ad74758696..c618f7cb5f0e 100644 --- a/fs/xfs/xfs_mount.h +++ b/fs/xfs/xfs_mount.h @@ -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) @@ -573,6 +565,21 @@ xfs_daddr_to_agbno(struct xfs_mount *mp, xfs_daddr_t d) } /* + * 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 */ #ifdef HAVE_PERCPU_SB @@ -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); diff --git a/fs/xfs/xfs_qmops.c b/fs/xfs/xfs_qmops.c index 0d594ed7efef..c266a0184b42 100644 --- a/fs/xfs/xfs_qmops.c +++ b/fs/xfs/xfs_qmops.c @@ -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); +} diff --git a/fs/xfs/xfs_quota.h b/fs/xfs/xfs_quota.h index 6f14df976f73..12c4ec775af8 100644 --- a/fs/xfs/xfs_quota.h +++ b/fs/xfs/xfs_quota.h @@ -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__ */ diff --git a/fs/xfs/xfs_rename.c b/fs/xfs/xfs_rename.c index 7679d7a7022d..44ea0ba36476 100644 --- a/fs/xfs/xfs_rename.c +++ b/fs/xfs/xfs_rename.c @@ -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, diff --git a/fs/xfs/xfs_rw.c b/fs/xfs/xfs_rw.c index 905d1c008be7..cd3ece6cc918 100644 --- a/fs/xfs/xfs_rw.c +++ b/fs/xfs/xfs_rw.c @@ -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)) { diff --git a/fs/xfs/xfs_rw.h b/fs/xfs/xfs_rw.h index fcf28dbded7c..49875e1d129f 100644 --- a/fs/xfs/xfs_rw.h +++ b/fs/xfs/xfs_rw.h @@ -23,32 +23,6 @@ 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 * file is a real time file or not, because the bmap code @@ -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); diff --git a/fs/xfs/xfs_sb.h b/fs/xfs/xfs_sb.h index ef42537a607a..94660b1a6ccc 100644 --- a/fs/xfs/xfs_sb.h +++ b/fs/xfs/xfs_sb.h @@ -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 */ @@ -146,6 +148,66 @@ typedef struct xfs_sb } 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. */ typedef enum { @@ -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, \ diff --git a/fs/xfs/xfs_trans.c b/fs/xfs/xfs_trans.c index 356d6627f581..8878322ee793 100644 --- a/fs/xfs/xfs_trans.c +++ b/fs/xfs/xfs_trans.c @@ -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; } /* diff --git a/fs/xfs/xfs_trans_ail.c b/fs/xfs/xfs_trans_ail.c index ceb4f6e99960..5b2ff59f19cf 100644 --- a/fs/xfs/xfs_trans_ail.c +++ b/fs/xfs/xfs_trans_ail.c @@ -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" diff --git a/fs/xfs/xfs_trans_extfree.c b/fs/xfs/xfs_trans_extfree.c index b290270dd4a6..27cce2a9c7e9 100644 --- a/fs/xfs/xfs_trans_extfree.c +++ b/fs/xfs/xfs_trans_extfree.c @@ -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" diff --git a/fs/xfs/xfs_types.h b/fs/xfs/xfs_types.h index 104f64a98790..5c89be475464 100644 --- a/fs/xfs/xfs_types.h +++ b/fs/xfs/xfs_types.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; diff --git a/fs/xfs/xfs_utils.c b/fs/xfs/xfs_utils.c index 20ffec308e1e..673b405eaa31 100644 --- a/fs/xfs/xfs_utils.c +++ b/fs/xfs/xfs_utils.c @@ -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) { diff --git a/fs/xfs/xfs_utils.h b/fs/xfs/xfs_utils.h index fe953e98afa7..a00b26d8840e 100644 --- a/fs/xfs/xfs_utils.h +++ b/fs/xfs/xfs_utils.h @@ -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, diff --git a/fs/xfs/xfs_vfsops.c b/fs/xfs/xfs_vfsops.c index 11f5ea29a038..a5a8454f2a63 100644 --- a/fs/xfs/xfs_vfsops.c +++ b/fs/xfs/xfs_vfsops.c @@ -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, -}; diff --git a/fs/xfs/xfs_vfsops.h b/fs/xfs/xfs_vfsops.h new file mode 100644 index 000000000000..bc99e3eb7dbb --- /dev/null +++ b/fs/xfs/xfs_vfsops.h @@ -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 */ diff --git a/fs/xfs/xfs_vnodeops.c b/fs/xfs/xfs_vnodeops.c index 603459229904..5e3c57ca9981 100644 --- a/fs/xfs/xfs_vnodeops.c +++ b/fs/xfs/xfs_vnodeops.c @@ -52,15 +52,13 @@ #include "xfs_trans_space.h" #include "xfs_log_priv.h" #include "xfs_filestream.h" +#include "xfs_vnodeops.h" -STATIC int +int xfs_open( - bhv_desc_t *bdp, - cred_t *credp) + xfs_inode_t *ip) { int mode; - bhv_vnode_t *vp = BHV_TO_VNODE(bdp); - xfs_inode_t *ip = XFS_BHVTOI(bdp); if (XFS_FORCED_SHUTDOWN(ip->i_mount)) return XFS_ERROR(EIO); @@ -69,7 +67,7 @@ xfs_open( * If it's a directory with any blocks, read-ahead block 0 * as we're almost certain to have the next operation be a read there. */ - if (VN_ISDIR(vp) && ip->i_d.di_nextents > 0) { + if (S_ISDIR(ip->i_d.di_mode) && ip->i_d.di_nextents > 0) { mode = xfs_ilock_map_shared(ip); if (ip->i_d.di_nextents > 0) (void)xfs_da_reada_buf(NULL, ip, 0, XFS_DATA_FORK); @@ -81,22 +79,16 @@ xfs_open( /* * xfs_getattr */ -STATIC int +int xfs_getattr( - bhv_desc_t *bdp, + xfs_inode_t *ip, bhv_vattr_t *vap, - int flags, - cred_t *credp) + int flags) { - xfs_inode_t *ip; - xfs_mount_t *mp; - bhv_vnode_t *vp; - - vp = BHV_TO_VNODE(bdp); - vn_trace_entry(vp, __FUNCTION__, (inst_t *)__return_address); + bhv_vnode_t *vp = XFS_ITOV(ip); + xfs_mount_t *mp = ip->i_mount; - ip = XFS_BHVTOI(bdp); - mp = ip->i_mount; + vn_trace_entry(ip, __FUNCTION__, (inst_t *)__return_address); if (XFS_FORCED_SHUTDOWN(mp)) return XFS_ERROR(EIO); @@ -215,14 +207,14 @@ xfs_getattr( */ int xfs_setattr( - bhv_desc_t *bdp, + xfs_inode_t *ip, bhv_vattr_t *vap, int flags, cred_t *credp) { - xfs_inode_t *ip; + bhv_vnode_t *vp = XFS_ITOV(ip); + xfs_mount_t *mp = ip->i_mount; xfs_trans_t *tp; - xfs_mount_t *mp; int mask; int code; uint lock_flags; @@ -230,17 +222,15 @@ xfs_setattr( uid_t uid=0, iuid=0; gid_t gid=0, igid=0; int timeflags = 0; - bhv_vnode_t *vp; xfs_prid_t projid=0, iprojid=0; int mandlock_before, mandlock_after; struct xfs_dquot *udqp, *gdqp, *olddquot1, *olddquot2; int file_owner; int need_iolock = 1; - vp = BHV_TO_VNODE(bdp); - vn_trace_entry(vp, __FUNCTION__, (inst_t *)__return_address); + vn_trace_entry(ip, __FUNCTION__, (inst_t *)__return_address); - if (vp->v_vfsp->vfs_flag & VFS_RDONLY) + if (mp->m_flags & XFS_MOUNT_RDONLY) return XFS_ERROR(EROFS); /* @@ -251,9 +241,6 @@ xfs_setattr( return XFS_ERROR(EINVAL); } - ip = XFS_BHVTOI(bdp); - mp = ip->i_mount; - if (XFS_FORCED_SHUTDOWN(mp)) return XFS_ERROR(EIO); @@ -337,7 +324,7 @@ xfs_setattr( } } } else { - if (DM_EVENT_ENABLED (vp->v_vfsp, ip, DM_EVENT_TRUNCATE) && + if (DM_EVENT_ENABLED(ip, DM_EVENT_TRUNCATE) && !(flags & ATTR_DMI)) { int dmflags = AT_DELAY_FLAG(flags) | DM_SEM_FLAG_WR; code = XFS_SEND_DATA(mp, DM_EVENT_TRUNCATE, vp, @@ -605,13 +592,13 @@ xfs_setattr( if (!code && (ip->i_size != ip->i_d.di_size) && (vap->va_size > ip->i_d.di_size)) { - code = bhv_vop_flush_pages(XFS_ITOV(ip), + code = xfs_flush_pages(ip, ip->i_d.di_size, vap->va_size, XFS_B_ASYNC, FI_NONE); } /* wait for all I/O to complete */ - vn_iowait(vp); + vn_iowait(ip); if (!code) code = xfs_itruncate_data(ip, vap->va_size); @@ -673,7 +660,7 @@ xfs_setattr( * vnode and flush it when the file is closed, and * do not wait the usual (long) time for writeout. */ - VTRUNCATE(vp); + xfs_iflags_set(ip, XFS_ITRUNCATED); } /* * Have to do this even if the file's size doesn't change. @@ -877,10 +864,6 @@ xfs_setattr( * racing calls to vop_vnode_change. */ mandlock_after = MANDLOCK(vp, ip->i_d.di_mode); - if (mandlock_before != mandlock_after) { - bhv_vop_vnode_change(vp, VCHANGE_FLAGS_ENF_LOCKING, - mandlock_after); - } xfs_iunlock(ip, lock_flags); @@ -896,7 +879,7 @@ xfs_setattr( return code; } - if (DM_EVENT_ENABLED(vp->v_vfsp, ip, DM_EVENT_ATTRIBUTE) && + if (DM_EVENT_ENABLED(ip, DM_EVENT_ATTRIBUTE) && !(flags & ATTR_DMI)) { (void) XFS_SEND_NAMESP(mp, DM_EVENT_ATTRIBUTE, vp, DM_RIGHT_NULL, NULL, DM_RIGHT_NULL, NULL, NULL, @@ -924,19 +907,16 @@ xfs_setattr( * xfs_access * Null conversion from vnode mode bits to inode mode bits, as in efs. */ -STATIC int +int xfs_access( - bhv_desc_t *bdp, + xfs_inode_t *ip, int mode, cred_t *credp) { - xfs_inode_t *ip; int error; - vn_trace_entry(BHV_TO_VNODE(bdp), __FUNCTION__, - (inst_t *)__return_address); + vn_trace_entry(ip, __FUNCTION__, (inst_t *)__return_address); - ip = XFS_BHVTOI(bdp); xfs_ilock(ip, XFS_ILOCK_SHARED); error = xfs_iaccess(ip, mode, credp); xfs_iunlock(ip, XFS_ILOCK_SHARED); @@ -951,105 +931,88 @@ xfs_access( */ #define SYMLINK_MAPS 2 -/* - * xfs_readlink - * - */ STATIC int -xfs_readlink( - bhv_desc_t *bdp, - uio_t *uiop, - int ioflags, - cred_t *credp) +xfs_readlink_bmap( + xfs_inode_t *ip, + char *link) { - xfs_inode_t *ip; - int count; - xfs_off_t offset; - int pathlen; - bhv_vnode_t *vp; - int error = 0; - xfs_mount_t *mp; - int nmaps; + xfs_mount_t *mp = ip->i_mount; + int pathlen = ip->i_d.di_size; + int nmaps = SYMLINK_MAPS; xfs_bmbt_irec_t mval[SYMLINK_MAPS]; xfs_daddr_t d; int byte_cnt; int n; xfs_buf_t *bp; + int error = 0; - vp = BHV_TO_VNODE(bdp); - vn_trace_entry(vp, __FUNCTION__, (inst_t *)__return_address); - - ip = XFS_BHVTOI(bdp); - mp = ip->i_mount; + error = xfs_bmapi(NULL, ip, 0, XFS_B_TO_FSB(mp, pathlen), 0, NULL, 0, + mval, &nmaps, NULL, NULL); + if (error) + goto out; - if (XFS_FORCED_SHUTDOWN(mp)) - return XFS_ERROR(EIO); + for (n = 0; n < nmaps; n++) { + d = XFS_FSB_TO_DADDR(mp, mval[n].br_startblock); + byte_cnt = XFS_FSB_TO_B(mp, mval[n].br_blockcount); - xfs_ilock(ip, XFS_ILOCK_SHARED); + bp = xfs_buf_read(mp->m_ddev_targp, d, BTOBB(byte_cnt), 0); + error = XFS_BUF_GETERROR(bp); + if (error) { + xfs_ioerror_alert("xfs_readlink", + ip->i_mount, bp, XFS_BUF_ADDR(bp)); + xfs_buf_relse(bp); + goto out; + } + if (pathlen < byte_cnt) + byte_cnt = pathlen; + pathlen -= byte_cnt; - ASSERT((ip->i_d.di_mode & S_IFMT) == S_IFLNK); + memcpy(link, XFS_BUF_PTR(bp), byte_cnt); + xfs_buf_relse(bp); + } - offset = uiop->uio_offset; - count = uiop->uio_resid; + link[ip->i_d.di_size] = '\0'; + error = 0; - if (offset < 0) { - error = XFS_ERROR(EINVAL); - goto error_return; - } - if (count <= 0) { - error = 0; - goto error_return; - } + out: + return error; +} - /* - * See if the symlink is stored inline. - */ - pathlen = (int)ip->i_d.di_size; +int +xfs_readlink( + xfs_inode_t *ip, + char *link) +{ + xfs_mount_t *mp = ip->i_mount; + int pathlen; + int error = 0; - if (ip->i_df.if_flags & XFS_IFINLINE) { - error = xfs_uio_read(ip->i_df.if_u1.if_data, pathlen, uiop); - } - else { - /* - * Symlink not inline. Call bmap to get it in. - */ - nmaps = SYMLINK_MAPS; + vn_trace_entry(ip, __FUNCTION__, (inst_t *)__return_address); - error = xfs_bmapi(NULL, ip, 0, XFS_B_TO_FSB(mp, pathlen), - 0, NULL, 0, mval, &nmaps, NULL, NULL); + if (XFS_FORCED_SHUTDOWN(mp)) + return XFS_ERROR(EIO); - if (error) { - goto error_return; - } + xfs_ilock(ip, XFS_ILOCK_SHARED); - for (n = 0; n < nmaps; n++) { - d = XFS_FSB_TO_DADDR(mp, mval[n].br_startblock); - byte_cnt = XFS_FSB_TO_B(mp, mval[n].br_blockcount); - bp = xfs_buf_read(mp->m_ddev_targp, d, - BTOBB(byte_cnt), 0); - error = XFS_BUF_GETERROR(bp); - if (error) { - xfs_ioerror_alert("xfs_readlink", - ip->i_mount, bp, XFS_BUF_ADDR(bp)); - xfs_buf_relse(bp); - goto error_return; - } - if (pathlen < byte_cnt) - byte_cnt = pathlen; - pathlen -= byte_cnt; + ASSERT((ip->i_d.di_mode & S_IFMT) == S_IFLNK); + ASSERT(ip->i_d.di_size <= MAXPATHLEN); - error = xfs_uio_read(XFS_BUF_PTR(bp), byte_cnt, uiop); - xfs_buf_relse (bp); - } + pathlen = ip->i_d.di_size; + if (!pathlen) + goto out; + if (ip->i_df.if_flags & XFS_IFINLINE) { + memcpy(link, ip->i_df.if_u1.if_data, pathlen); + link[pathlen] = '\0'; + } else { + error = xfs_readlink_bmap(ip, link); } -error_return: + out: xfs_iunlock(ip, XFS_ILOCK_SHARED); return error; } - /* * xfs_fsync * @@ -1059,23 +1022,18 @@ error_return: * be held while flushing the data, so acquire after we're done * with that. */ -STATIC int +int xfs_fsync( - bhv_desc_t *bdp, + xfs_inode_t *ip, int flag, - cred_t *credp, xfs_off_t start, xfs_off_t stop) { - xfs_inode_t *ip; xfs_trans_t *tp; int error; int log_flushed = 0, changed = 1; - vn_trace_entry(BHV_TO_VNODE(bdp), - __FUNCTION__, (inst_t *)__return_address); - - ip = XFS_BHVTOI(bdp); + vn_trace_entry(ip, __FUNCTION__, (inst_t *)__return_address); ASSERT(start >= 0 && stop >= -1); @@ -1545,27 +1503,24 @@ xfs_inactive_attrs( return 0; } -STATIC int +int xfs_release( - bhv_desc_t *bdp) + xfs_inode_t *ip) { - xfs_inode_t *ip; - bhv_vnode_t *vp; - xfs_mount_t *mp; + bhv_vnode_t *vp = XFS_ITOV(ip); + xfs_mount_t *mp = ip->i_mount; int error; - vp = BHV_TO_VNODE(bdp); - ip = XFS_BHVTOI(bdp); - mp = ip->i_mount; - if (!VN_ISREG(vp) || (ip->i_d.di_mode == 0)) return 0; /* If this is a read-only mount, don't do this (would generate I/O) */ - if (vp->v_vfsp->vfs_flag & VFS_RDONLY) + if (mp->m_flags & XFS_MOUNT_RDONLY) return 0; if (!XFS_FORCED_SHUTDOWN(mp)) { + int truncated; + /* * If we are using filestreams, and we have an unlinked * file that we are processing the last close on, then nothing @@ -1586,8 +1541,9 @@ xfs_release( * significantly reducing the time window where we'd otherwise * be exposed to that problem. */ - if (VUNTRUNCATE(vp) && VN_DIRTY(vp) && ip->i_delayed_blks > 0) - bhv_vop_flush_pages(vp, 0, -1, XFS_B_ASYNC, FI_NONE); + truncated = xfs_iflags_test_and_clear(ip, XFS_ITRUNCATED); + if (truncated && VN_DIRTY(vp) && ip->i_delayed_blks > 0) + xfs_flush_pages(ip, 0, -1, XFS_B_ASYNC, FI_NONE); } #ifdef HAVE_REFCACHE @@ -1623,13 +1579,11 @@ xfs_release( * now be truncated. Also, we clear all of the read-ahead state * kept for the inode here since the file is now closed. */ -STATIC int +int xfs_inactive( - bhv_desc_t *bdp, - cred_t *credp) + xfs_inode_t *ip) { - xfs_inode_t *ip; - bhv_vnode_t *vp; + bhv_vnode_t *vp = XFS_ITOV(ip); xfs_bmap_free_t free_list; xfs_fsblock_t first_block; int committed; @@ -1638,10 +1592,7 @@ xfs_inactive( int error; int truncate; - vp = BHV_TO_VNODE(bdp); - vn_trace_entry(vp, __FUNCTION__, (inst_t *)__return_address); - - ip = XFS_BHVTOI(bdp); + vn_trace_entry(ip, __FUNCTION__, (inst_t *)__return_address); /* * If the inode is already free, then there can be nothing @@ -1666,15 +1617,14 @@ xfs_inactive( mp = ip->i_mount; - if (ip->i_d.di_nlink == 0 && - DM_EVENT_ENABLED(vp->v_vfsp, ip, DM_EVENT_DESTROY)) { + if (ip->i_d.di_nlink == 0 && DM_EVENT_ENABLED(ip, DM_EVENT_DESTROY)) { (void) XFS_SEND_DESTROY(mp, vp, DM_RIGHT_NULL); } error = 0; /* If this is a read-only mount, don't do this (would generate I/O) */ - if (vp->v_vfsp->vfs_flag & VFS_RDONLY) + if (mp->m_flags & XFS_MOUNT_RDONLY) goto out; if (ip->i_d.di_nlink != 0) { @@ -1844,34 +1794,24 @@ xfs_inactive( } -/* - * xfs_lookup - */ -STATIC int +int xfs_lookup( - bhv_desc_t *dir_bdp, + xfs_inode_t *dp, bhv_vname_t *dentry, - bhv_vnode_t **vpp, - int flags, - bhv_vnode_t *rdir, - cred_t *credp) + bhv_vnode_t **vpp) { - xfs_inode_t *dp, *ip; + xfs_inode_t *ip; xfs_ino_t e_inum; int error; uint lock_mode; - bhv_vnode_t *dir_vp; - - 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); if (XFS_FORCED_SHUTDOWN(dp->i_mount)) return XFS_ERROR(EIO); lock_mode = xfs_ilock_map_shared(dp); - error = xfs_dir_lookup_int(dir_bdp, lock_mode, dentry, &e_inum, &ip); + error = xfs_dir_lookup_int(dp, lock_mode, dentry, &e_inum, &ip); if (!error) { *vpp = XFS_ITOV(ip); ITRACE(ip); @@ -1880,53 +1820,43 @@ xfs_lookup( return error; } - -/* - * xfs_create (create a new file). - */ -STATIC int +int xfs_create( - bhv_desc_t *dir_bdp, + xfs_inode_t *dp, bhv_vname_t *dentry, - bhv_vattr_t *vap, + mode_t mode, + xfs_dev_t rdev, bhv_vnode_t **vpp, cred_t *credp) { char *name = VNAME(dentry); - bhv_vnode_t *dir_vp; - xfs_inode_t *dp, *ip; + xfs_mount_t *mp = dp->i_mount; + bhv_vnode_t *dir_vp = XFS_ITOV(dp); + xfs_inode_t *ip; bhv_vnode_t *vp = NULL; xfs_trans_t *tp; - xfs_mount_t *mp; - xfs_dev_t rdev; int error; xfs_bmap_free_t free_list; xfs_fsblock_t first_block; - boolean_t dp_joined_to_trans; + boolean_t unlock_dp_on_error = B_FALSE; int dm_event_sent = 0; uint cancel_flags; int committed; xfs_prid_t prid; struct xfs_dquot *udqp, *gdqp; uint resblks; - int dm_di_mode; int namelen; ASSERT(!*vpp); - dir_vp = BHV_TO_VNODE(dir_bdp); - vn_trace_entry(dir_vp, __FUNCTION__, (inst_t *)__return_address); + vn_trace_entry(dp, __FUNCTION__, (inst_t *)__return_address); - dp = XFS_BHVTOI(dir_bdp); - mp = dp->i_mount; - - dm_di_mode = vap->va_mode; namelen = VNAMELEN(dentry); - if (DM_EVENT_ENABLED(dir_vp->v_vfsp, dp, DM_EVENT_CREATE)) { + if (DM_EVENT_ENABLED(dp, DM_EVENT_CREATE)) { error = XFS_SEND_NAMESP(mp, DM_EVENT_CREATE, dir_vp, DM_RIGHT_NULL, NULL, DM_RIGHT_NULL, name, NULL, - dm_di_mode, 0, 0); + mode, 0, 0); if (error) return error; @@ -1941,8 +1871,6 @@ xfs_create( udqp = gdqp = NULL; if (dp->i_d.di_flags & XFS_DIFLAG_PROJINHERIT) prid = dp->i_d.di_projid; - else if (vap->va_mask & XFS_AT_PROJID) - prid = (xfs_prid_t)vap->va_projid; else prid = (xfs_prid_t)dfltprid; @@ -1956,7 +1884,6 @@ xfs_create( goto std_return; ip = NULL; - dp_joined_to_trans = B_FALSE; tp = xfs_trans_alloc(mp, XFS_TRANS_CREATE); cancel_flags = XFS_TRANS_RELEASE_LOG_RES; @@ -1976,11 +1903,11 @@ xfs_create( } if (error) { cancel_flags = 0; - dp = NULL; goto error_return; } xfs_ilock(dp, XFS_ILOCK_EXCL | XFS_ILOCK_PARENT); + unlock_dp_on_error = B_TRUE; XFS_BMAP_INIT(&free_list, &first_block); @@ -1995,8 +1922,7 @@ xfs_create( if (resblks == 0 && (error = xfs_dir_canenter(tp, dp, name, namelen))) goto error_return; - rdev = (vap->va_mask & XFS_AT_RDEV) ? vap->va_rdev : 0; - error = xfs_dir_ialloc(&tp, dp, vap->va_mode, 1, + error = xfs_dir_ialloc(&tp, dp, mode, 1, rdev, credp, prid, resblks > 0, &ip, &committed); if (error) { @@ -2014,15 +1940,15 @@ xfs_create( ASSERT(ismrlocked (&ip->i_lock, MR_UPDATE)); /* - * Now we join the directory inode to the transaction. - * We do not do it earlier because xfs_dir_ialloc - * might commit the previous transaction (and release - * all the locks). + * Now we join the directory inode to the transaction. We do not do it + * earlier because xfs_dir_ialloc might commit the previous transaction + * (and release all the locks). An error from here on will result in + * the transaction cancel unlocking dp so don't do it explicitly in the + * error path. */ - VN_HOLD(dir_vp); xfs_trans_ijoin(tp, dp, XFS_ILOCK_EXCL); - dp_joined_to_trans = B_TRUE; + unlock_dp_on_error = B_FALSE; error = xfs_dir_createname(tp, dp, name, namelen, ip->i_ino, &first_block, &free_list, resblks ? @@ -2076,25 +2002,18 @@ xfs_create( XFS_QM_DQRELE(mp, udqp); XFS_QM_DQRELE(mp, gdqp); - /* - * Propagate the fact that the vnode changed after the - * xfs_inode locks have been released. - */ - bhv_vop_vnode_change(vp, VCHANGE_FLAGS_TRUNCATED, 3); - *vpp = vp; /* Fallthrough to std_return with error = 0 */ std_return: - if ( (*vpp || (error != 0 && dm_event_sent != 0)) && - DM_EVENT_ENABLED(dir_vp->v_vfsp, XFS_BHVTOI(dir_bdp), - DM_EVENT_POSTCREATE)) { + if ((*vpp || (error != 0 && dm_event_sent != 0)) && + DM_EVENT_ENABLED(dp, DM_EVENT_POSTCREATE)) { (void) XFS_SEND_NAMESP(mp, DM_EVENT_POSTCREATE, dir_vp, DM_RIGHT_NULL, *vpp ? vp:NULL, DM_RIGHT_NULL, name, NULL, - dm_di_mode, error, 0); + mode, error, 0); } return error; @@ -2106,11 +2025,12 @@ std_return: if (tp != NULL) xfs_trans_cancel(tp, cancel_flags); - if (!dp_joined_to_trans && (dp != NULL)) - xfs_iunlock(dp, XFS_ILOCK_EXCL); XFS_QM_DQRELE(mp, udqp); XFS_QM_DQRELE(mp, gdqp); + if (unlock_dp_on_error) + xfs_iunlock(dp, XFS_ILOCK_EXCL); + goto std_return; abort_rele: @@ -2381,22 +2301,16 @@ int remove_which_error_return = 0; #define REMOVE_DEBUG_TRACE(x) #endif /* ! DEBUG */ - -/* - * xfs_remove - * - */ -STATIC int +int xfs_remove( - bhv_desc_t *dir_bdp, - bhv_vname_t *dentry, - cred_t *credp) + xfs_inode_t *dp, + bhv_vname_t *dentry) { - bhv_vnode_t *dir_vp; + bhv_vnode_t *dir_vp = XFS_ITOV(dp); char *name = VNAME(dentry); - xfs_inode_t *dp, *ip; + xfs_mount_t *mp = dp->i_mount; + xfs_inode_t *ip; xfs_trans_t *tp = NULL; - xfs_mount_t *mp; int error = 0; xfs_bmap_free_t free_list; xfs_fsblock_t first_block; @@ -2407,11 +2321,7 @@ xfs_remove( uint resblks; int namelen; - dir_vp = BHV_TO_VNODE(dir_bdp); - vn_trace_entry(dir_vp, __FUNCTION__, (inst_t *)__return_address); - - dp = XFS_BHVTOI(dir_bdp); - mp = dp->i_mount; + vn_trace_entry(dp, __FUNCTION__, (inst_t *)__return_address); if (XFS_FORCED_SHUTDOWN(mp)) return XFS_ERROR(EIO); @@ -2423,7 +2333,7 @@ xfs_remove( IRELE(ip); } - if (DM_EVENT_ENABLED(dir_vp->v_vfsp, dp, DM_EVENT_REMOVE)) { + if (DM_EVENT_ENABLED(dp, DM_EVENT_REMOVE)) { error = XFS_SEND_NAMESP(mp, DM_EVENT_REMOVE, dir_vp, DM_RIGHT_NULL, NULL, DM_RIGHT_NULL, name, NULL, dm_di_mode, 0, 0); @@ -2454,7 +2364,7 @@ xfs_remove( dm_di_mode = ip->i_d.di_mode; - vn_trace_entry(XFS_ITOV(ip), __FUNCTION__, (inst_t *)__return_address); + vn_trace_entry(ip, __FUNCTION__, (inst_t *)__return_address); ITRACE(ip); @@ -2588,19 +2498,13 @@ xfs_remove( if (link_zero && xfs_inode_is_filestream(ip)) xfs_filestream_deassociate(ip); - vn_trace_exit(XFS_ITOV(ip), __FUNCTION__, (inst_t *)__return_address); - - /* - * Let interposed file systems know about removed links. - */ - bhv_vop_link_removed(XFS_ITOV(ip), dir_vp, link_zero); + vn_trace_exit(ip, __FUNCTION__, (inst_t *)__return_address); IRELE(ip); /* Fall through to std_return with error = 0 */ std_return: - if (DM_EVENT_ENABLED(dir_vp->v_vfsp, dp, - DM_EVENT_POSTREMOVE)) { + if (DM_EVENT_ENABLED(dp, DM_EVENT_POSTREMOVE)) { (void) XFS_SEND_NAMESP(mp, DM_EVENT_POSTREMOVE, dir_vp, DM_RIGHT_NULL, NULL, DM_RIGHT_NULL, @@ -2638,46 +2542,36 @@ xfs_remove( goto std_return; } - -/* - * xfs_link - * - */ -STATIC int +int xfs_link( - bhv_desc_t *target_dir_bdp, + xfs_inode_t *tdp, bhv_vnode_t *src_vp, - bhv_vname_t *dentry, - cred_t *credp) + bhv_vname_t *dentry) { - xfs_inode_t *tdp, *sip; + bhv_vnode_t *target_dir_vp = XFS_ITOV(tdp); + xfs_mount_t *mp = tdp->i_mount; + xfs_inode_t *sip = xfs_vtoi(src_vp); xfs_trans_t *tp; - xfs_mount_t *mp; xfs_inode_t *ips[2]; int error; xfs_bmap_free_t free_list; xfs_fsblock_t first_block; int cancel_flags; int committed; - bhv_vnode_t *target_dir_vp; int resblks; char *target_name = VNAME(dentry); int target_namelen; - target_dir_vp = BHV_TO_VNODE(target_dir_bdp); - vn_trace_entry(target_dir_vp, __FUNCTION__, (inst_t *)__return_address); - vn_trace_entry(src_vp, __FUNCTION__, (inst_t *)__return_address); + vn_trace_entry(tdp, __FUNCTION__, (inst_t *)__return_address); + vn_trace_entry(xfs_vtoi(src_vp), __FUNCTION__, (inst_t *)__return_address); target_namelen = VNAMELEN(dentry); ASSERT(!VN_ISDIR(src_vp)); - sip = xfs_vtoi(src_vp); - tdp = XFS_BHVTOI(target_dir_bdp); - mp = tdp->i_mount; if (XFS_FORCED_SHUTDOWN(mp)) return XFS_ERROR(EIO); - if (DM_EVENT_ENABLED(src_vp->v_vfsp, tdp, DM_EVENT_LINK)) { + if (DM_EVENT_ENABLED(tdp, DM_EVENT_LINK)) { error = XFS_SEND_NAMESP(mp, DM_EVENT_LINK, target_dir_vp, DM_RIGHT_NULL, src_vp, DM_RIGHT_NULL, @@ -2788,8 +2682,7 @@ xfs_link( /* Fall through to std_return with error = 0. */ std_return: - if (DM_EVENT_ENABLED(src_vp->v_vfsp, sip, - DM_EVENT_POSTLINK)) { + if (DM_EVENT_ENABLED(sip, DM_EVENT_POSTLINK)) { (void) XFS_SEND_NAMESP(mp, DM_EVENT_POSTLINK, target_dir_vp, DM_RIGHT_NULL, src_vp, DM_RIGHT_NULL, @@ -2807,57 +2700,43 @@ std_return: } -/* - * xfs_mkdir - * - */ -STATIC int +int xfs_mkdir( - bhv_desc_t *dir_bdp, + xfs_inode_t *dp, bhv_vname_t *dentry, - bhv_vattr_t *vap, + mode_t mode, bhv_vnode_t **vpp, cred_t *credp) { + bhv_vnode_t *dir_vp = XFS_ITOV(dp); char *dir_name = VNAME(dentry); - xfs_inode_t *dp; + int dir_namelen = VNAMELEN(dentry); + xfs_mount_t *mp = dp->i_mount; xfs_inode_t *cdp; /* inode of created dir */ bhv_vnode_t *cvp; /* vnode of created dir */ xfs_trans_t *tp; - xfs_mount_t *mp; int cancel_flags; int error; int committed; xfs_bmap_free_t free_list; xfs_fsblock_t first_block; - bhv_vnode_t *dir_vp; - boolean_t dp_joined_to_trans; + boolean_t unlock_dp_on_error = B_FALSE; boolean_t created = B_FALSE; int dm_event_sent = 0; xfs_prid_t prid; struct xfs_dquot *udqp, *gdqp; uint resblks; - int dm_di_mode; - int dir_namelen; - - dir_vp = BHV_TO_VNODE(dir_bdp); - dp = XFS_BHVTOI(dir_bdp); - mp = dp->i_mount; if (XFS_FORCED_SHUTDOWN(mp)) return XFS_ERROR(EIO); - dir_namelen = VNAMELEN(dentry); - tp = NULL; - dp_joined_to_trans = B_FALSE; - dm_di_mode = vap->va_mode; - if (DM_EVENT_ENABLED(dir_vp->v_vfsp, dp, DM_EVENT_CREATE)) { + if (DM_EVENT_ENABLED(dp, DM_EVENT_CREATE)) { error = XFS_SEND_NAMESP(mp, DM_EVENT_CREATE, dir_vp, DM_RIGHT_NULL, NULL, DM_RIGHT_NULL, dir_name, NULL, - dm_di_mode, 0, 0); + mode, 0, 0); if (error) return error; dm_event_sent = 1; @@ -2865,14 +2744,12 @@ xfs_mkdir( /* Return through std_return after this point. */ - vn_trace_entry(dir_vp, __FUNCTION__, (inst_t *)__return_address); + vn_trace_entry(dp, __FUNCTION__, (inst_t *)__return_address); mp = dp->i_mount; udqp = gdqp = NULL; if (dp->i_d.di_flags & XFS_DIFLAG_PROJINHERIT) prid = dp->i_d.di_projid; - else if (vap->va_mask & XFS_AT_PROJID) - prid = (xfs_prid_t)vap->va_projid; else prid = (xfs_prid_t)dfltprid; @@ -2898,11 +2775,11 @@ xfs_mkdir( } if (error) { cancel_flags = 0; - dp = NULL; goto error_return; } xfs_ilock(dp, XFS_ILOCK_EXCL | XFS_ILOCK_PARENT); + unlock_dp_on_error = B_TRUE; /* * Check for directory link count overflow. @@ -2925,7 +2802,7 @@ xfs_mkdir( /* * create the directory inode. */ - error = xfs_dir_ialloc(&tp, dp, vap->va_mode, 2, + error = xfs_dir_ialloc(&tp, dp, mode, 2, 0, credp, prid, resblks > 0, &cdp, NULL); if (error) { @@ -2939,11 +2816,13 @@ xfs_mkdir( * Now we add the directory inode to the transaction. * We waited until now since xfs_dir_ialloc might start * a new transaction. Had we joined the transaction - * earlier, the locks might have gotten released. + * earlier, the locks might have gotten released. An error + * from here on will result in the transaction cancel + * unlocking dp so don't do it explicitly in the error path. */ VN_HOLD(dir_vp); xfs_trans_ijoin(tp, dp, XFS_ILOCK_EXCL); - dp_joined_to_trans = B_TRUE; + unlock_dp_on_error = B_FALSE; XFS_BMAP_INIT(&free_list, &first_block); @@ -3010,15 +2889,14 @@ xfs_mkdir( * xfs_trans_commit. */ std_return: - if ( (created || (error != 0 && dm_event_sent != 0)) && - DM_EVENT_ENABLED(dir_vp->v_vfsp, XFS_BHVTOI(dir_bdp), - DM_EVENT_POSTCREATE)) { + if ((created || (error != 0 && dm_event_sent != 0)) && + DM_EVENT_ENABLED(dp, DM_EVENT_POSTCREATE)) { (void) XFS_SEND_NAMESP(mp, DM_EVENT_POSTCREATE, dir_vp, DM_RIGHT_NULL, created ? XFS_ITOV(cdp):NULL, DM_RIGHT_NULL, dir_name, NULL, - dm_di_mode, error, 0); + mode, error, 0); } return error; @@ -3032,56 +2910,43 @@ std_return: XFS_QM_DQRELE(mp, udqp); XFS_QM_DQRELE(mp, gdqp); - if (!dp_joined_to_trans && (dp != NULL)) { + if (unlock_dp_on_error) xfs_iunlock(dp, XFS_ILOCK_EXCL); - } goto std_return; } - -/* - * xfs_rmdir - * - */ -STATIC int +int xfs_rmdir( - bhv_desc_t *dir_bdp, - bhv_vname_t *dentry, - cred_t *credp) + xfs_inode_t *dp, + bhv_vname_t *dentry) { + bhv_vnode_t *dir_vp = XFS_ITOV(dp); char *name = VNAME(dentry); - xfs_inode_t *dp; - xfs_inode_t *cdp; /* child directory */ + int namelen = VNAMELEN(dentry); + xfs_mount_t *mp = dp->i_mount; + xfs_inode_t *cdp; /* child directory */ xfs_trans_t *tp; - xfs_mount_t *mp; int error; xfs_bmap_free_t free_list; xfs_fsblock_t first_block; int cancel_flags; int committed; - bhv_vnode_t *dir_vp; int dm_di_mode = S_IFDIR; int last_cdp_link; - int namelen; uint resblks; - dir_vp = BHV_TO_VNODE(dir_bdp); - dp = XFS_BHVTOI(dir_bdp); - mp = dp->i_mount; - - vn_trace_entry(dir_vp, __FUNCTION__, (inst_t *)__return_address); + vn_trace_entry(dp, __FUNCTION__, (inst_t *)__return_address); - if (XFS_FORCED_SHUTDOWN(XFS_BHVTOI(dir_bdp)->i_mount)) + if (XFS_FORCED_SHUTDOWN(mp)) return XFS_ERROR(EIO); - namelen = VNAMELEN(dentry); if (!xfs_get_dir_entry(dentry, &cdp)) { dm_di_mode = cdp->i_d.di_mode; IRELE(cdp); } - if (DM_EVENT_ENABLED(dir_vp->v_vfsp, dp, DM_EVENT_REMOVE)) { + if (DM_EVENT_ENABLED(dp, DM_EVENT_REMOVE)) { error = XFS_SEND_NAMESP(mp, DM_EVENT_REMOVE, dir_vp, DM_RIGHT_NULL, NULL, DM_RIGHT_NULL, @@ -3260,17 +3125,12 @@ xfs_rmdir( } - /* - * Let interposed file systems know about removed links. - */ - bhv_vop_link_removed(XFS_ITOV(cdp), dir_vp, last_cdp_link); - IRELE(cdp); /* Fall through to std_return with error = 0 or the errno * from xfs_trans_commit. */ std_return: - if (DM_EVENT_ENABLED(dir_vp->v_vfsp, dp, DM_EVENT_POSTREMOVE)) { + if (DM_EVENT_ENABLED(dp, DM_EVENT_POSTREMOVE)) { (void) XFS_SEND_NAMESP(mp, DM_EVENT_POSTREMOVE, dir_vp, DM_RIGHT_NULL, NULL, DM_RIGHT_NULL, @@ -3289,56 +3149,24 @@ xfs_rmdir( goto std_return; } - -/* - * Read dp's entries starting at uiop->uio_offset and translate them into - * bufsize bytes worth of struct dirents starting at bufbase. - */ -STATIC int -xfs_readdir( - bhv_desc_t *dir_bdp, - uio_t *uiop, - cred_t *credp, - int *eofp) -{ - xfs_inode_t *dp; - xfs_trans_t *tp = NULL; - int error = 0; - uint lock_mode; - - vn_trace_entry(BHV_TO_VNODE(dir_bdp), __FUNCTION__, - (inst_t *)__return_address); - dp = XFS_BHVTOI(dir_bdp); - - if (XFS_FORCED_SHUTDOWN(dp->i_mount)) - return XFS_ERROR(EIO); - - lock_mode = xfs_ilock_map_shared(dp); - error = xfs_dir_getdents(tp, dp, uiop, eofp); - xfs_iunlock_map_shared(dp, lock_mode); - return error; -} - - -STATIC int +int xfs_symlink( - bhv_desc_t *dir_bdp, + xfs_inode_t *dp, bhv_vname_t *dentry, - bhv_vattr_t *vap, char *target_path, + mode_t mode, bhv_vnode_t **vpp, cred_t *credp) { + bhv_vnode_t *dir_vp = XFS_ITOV(dp); + xfs_mount_t *mp = dp->i_mount; xfs_trans_t *tp; - xfs_mount_t *mp; - xfs_inode_t *dp; xfs_inode_t *ip; int error; int pathlen; xfs_bmap_free_t free_list; xfs_fsblock_t first_block; - boolean_t dp_joined_to_trans; - bhv_vnode_t *dir_vp; + boolean_t unlock_dp_on_error = B_FALSE; uint cancel_flags; int committed; xfs_fileoff_t first_fsb; @@ -3357,16 +3185,12 @@ xfs_symlink( int link_namelen; *vpp = NULL; - dir_vp = BHV_TO_VNODE(dir_bdp); - dp = XFS_BHVTOI(dir_bdp); - dp_joined_to_trans = B_FALSE; error = 0; ip = NULL; tp = NULL; - vn_trace_entry(dir_vp, __FUNCTION__, (inst_t *)__return_address); + vn_trace_entry(dp, __FUNCTION__, (inst_t *)__return_address); - mp = dp->i_mount; if (XFS_FORCED_SHUTDOWN(mp)) return XFS_ERROR(EIO); @@ -3405,7 +3229,7 @@ xfs_symlink( } } - if (DM_EVENT_ENABLED(dir_vp->v_vfsp, dp, DM_EVENT_SYMLINK)) { + if (DM_EVENT_ENABLED(dp, DM_EVENT_SYMLINK)) { error = XFS_SEND_NAMESP(mp, DM_EVENT_SYMLINK, dir_vp, DM_RIGHT_NULL, NULL, DM_RIGHT_NULL, link_name, target_path, 0, 0, 0); @@ -3418,8 +3242,6 @@ xfs_symlink( udqp = gdqp = NULL; if (dp->i_d.di_flags & XFS_DIFLAG_PROJINHERIT) prid = dp->i_d.di_projid; - else if (vap->va_mask & XFS_AT_PROJID) - prid = (xfs_prid_t)vap->va_projid; else prid = (xfs_prid_t)dfltprid; @@ -3452,11 +3274,11 @@ xfs_symlink( } if (error) { cancel_flags = 0; - dp = NULL; goto error_return; } xfs_ilock(dp, XFS_ILOCK_EXCL | XFS_ILOCK_PARENT); + unlock_dp_on_error = B_TRUE; /* * Check whether the directory allows new symlinks or not. @@ -3488,7 +3310,7 @@ xfs_symlink( /* * Allocate an inode for the symlink. */ - error = xfs_dir_ialloc(&tp, dp, S_IFLNK | (vap->va_mode&~S_IFMT), + error = xfs_dir_ialloc(&tp, dp, S_IFLNK | (mode & ~S_IFMT), 1, 0, credp, prid, resblks > 0, &ip, NULL); if (error) { if (error == ENOSPC) @@ -3497,9 +3319,14 @@ xfs_symlink( } ITRACE(ip); + /* + * An error after we've joined dp to the transaction will result in the + * transaction cancel unlocking dp so don't do it explicitly in the + * error path. + */ VN_HOLD(dir_vp); xfs_trans_ijoin(tp, dp, XFS_ILOCK_EXCL); - dp_joined_to_trans = B_TRUE; + unlock_dp_on_error = B_FALSE; /* * Also attach the dquot(s) to it, if applicable. @@ -3605,8 +3432,7 @@ xfs_symlink( /* Fall through to std_return with error = 0 or errno from * xfs_trans_commit */ std_return: - if (DM_EVENT_ENABLED(dir_vp->v_vfsp, XFS_BHVTOI(dir_bdp), - DM_EVENT_POSTSYMLINK)) { + if (DM_EVENT_ENABLED(dp, DM_EVENT_POSTSYMLINK)) { (void) XFS_SEND_NAMESP(mp, DM_EVENT_POSTSYMLINK, dir_vp, DM_RIGHT_NULL, error ? NULL : XFS_ITOV(ip), @@ -3633,9 +3459,8 @@ std_return: XFS_QM_DQRELE(mp, udqp); XFS_QM_DQRELE(mp, gdqp); - if (!dp_joined_to_trans && (dp != NULL)) { + if (unlock_dp_on_error) xfs_iunlock(dp, XFS_ILOCK_EXCL); - } goto std_return; } @@ -3647,20 +3472,16 @@ std_return: * A fid routine that takes a pointer to a previously allocated * fid structure (like xfs_fast_fid) but uses a 64 bit inode number. */ -STATIC int +int xfs_fid2( - bhv_desc_t *bdp, + xfs_inode_t *ip, fid_t *fidp) { - xfs_inode_t *ip; - xfs_fid2_t *xfid; + xfs_fid2_t *xfid = (xfs_fid2_t *)fidp; - vn_trace_entry(BHV_TO_VNODE(bdp), __FUNCTION__, - (inst_t *)__return_address); + vn_trace_entry(ip, __FUNCTION__, (inst_t *)__return_address); ASSERT(sizeof(fid_t) >= sizeof(xfs_fid2_t)); - xfid = (xfs_fid2_t *)fidp; - ip = XFS_BHVTOI(bdp); xfid->fid_len = sizeof(xfs_fid2_t) - sizeof(xfid->fid_len); xfid->fid_pad = 0; /* @@ -3674,21 +3495,13 @@ xfs_fid2( } -/* - * xfs_rwlock - */ int xfs_rwlock( - bhv_desc_t *bdp, + xfs_inode_t *ip, bhv_vrwlock_t locktype) { - xfs_inode_t *ip; - bhv_vnode_t *vp; - - vp = BHV_TO_VNODE(bdp); - if (VN_ISDIR(vp)) + if (S_ISDIR(ip->i_d.di_mode)) return 1; - ip = XFS_BHVTOI(bdp); if (locktype == VRWLOCK_WRITE) { xfs_ilock(ip, XFS_IOLOCK_EXCL); } else if (locktype == VRWLOCK_TRY_READ) { @@ -3705,21 +3518,13 @@ xfs_rwlock( } -/* - * xfs_rwunlock - */ void xfs_rwunlock( - bhv_desc_t *bdp, + xfs_inode_t *ip, bhv_vrwlock_t locktype) { - xfs_inode_t *ip; - bhv_vnode_t *vp; - - vp = BHV_TO_VNODE(bdp); - if (VN_ISDIR(vp)) - return; - ip = XFS_BHVTOI(bdp); + if (S_ISDIR(ip->i_d.di_mode)) + return; if (locktype == VRWLOCK_WRITE) { /* * In the write case, we may have added a new entry to @@ -3737,20 +3542,16 @@ xfs_rwunlock( return; } -STATIC int + +int xfs_inode_flush( - bhv_desc_t *bdp, + xfs_inode_t *ip, int flags) { - xfs_inode_t *ip; - xfs_mount_t *mp; - xfs_inode_log_item_t *iip; + xfs_mount_t *mp = ip->i_mount; + xfs_inode_log_item_t *iip = ip->i_itemp; int error = 0; - ip = XFS_BHVTOI(bdp); - mp = ip->i_mount; - iip = ip->i_itemp; - if (XFS_FORCED_SHUTDOWN(mp)) return XFS_ERROR(EIO); @@ -3819,24 +3620,20 @@ xfs_inode_flush( return error; } + int -xfs_set_dmattrs ( - bhv_desc_t *bdp, +xfs_set_dmattrs( + xfs_inode_t *ip, u_int evmask, - u_int16_t state, - cred_t *credp) + u_int16_t state) { - xfs_inode_t *ip; + xfs_mount_t *mp = ip->i_mount; xfs_trans_t *tp; - xfs_mount_t *mp; int error; if (!capable(CAP_SYS_ADMIN)) return XFS_ERROR(EPERM); - ip = XFS_BHVTOI(bdp); - mp = ip->i_mount; - if (XFS_FORCED_SHUTDOWN(mp)) return XFS_ERROR(EIO); @@ -3859,17 +3656,13 @@ xfs_set_dmattrs ( return error; } -STATIC int +int xfs_reclaim( - bhv_desc_t *bdp) + xfs_inode_t *ip) { - xfs_inode_t *ip; - bhv_vnode_t *vp; - - vp = BHV_TO_VNODE(bdp); - ip = XFS_BHVTOI(bdp); + bhv_vnode_t *vp = XFS_ITOV(ip); - vn_trace_entry(vp, __FUNCTION__, (inst_t *)__return_address); + vn_trace_entry(ip, __FUNCTION__, (inst_t *)__return_address); ASSERT(!VN_MAPPED(vp)); @@ -3879,7 +3672,7 @@ xfs_reclaim( return 0; } - vn_iowait(vp); + vn_iowait(ip); ASSERT(XFS_FORCED_SHUTDOWN(ip->i_mount) || ip->i_delayed_blks == 0); @@ -3911,7 +3704,8 @@ xfs_reclaim( XFS_MOUNT_ILOCK(mp); spin_lock(&ip->i_flags_lock); __xfs_iflags_set(ip, XFS_IRECLAIMABLE); - vn_bhv_remove(VN_BHV_HEAD(vp), XFS_ITOBHV(ip)); + vn_to_inode(vp)->i_private = NULL; + ip->i_vnode = NULL; spin_unlock(&ip->i_flags_lock); list_add_tail(&ip->i_reclaim, &mp->m_del_inodes); XFS_MOUNT_IUNLOCK(mp); @@ -3925,7 +3719,7 @@ xfs_finish_reclaim( int locked, int sync_mode) { - xfs_ihash_t *ih = ip->i_hash; + xfs_perag_t *pag = xfs_get_perag(ip->i_mount, ip->i_ino); bhv_vnode_t *vp = XFS_ITOV_NULL(ip); int error; @@ -3937,12 +3731,12 @@ xfs_finish_reclaim( * Once we have the XFS_IRECLAIM flag set it will not touch * us. */ - write_lock(&ih->ih_lock); + write_lock(&pag->pag_ici_lock); spin_lock(&ip->i_flags_lock); if (__xfs_iflags_test(ip, XFS_IRECLAIM) || (!__xfs_iflags_test(ip, XFS_IRECLAIMABLE) && vp == NULL)) { spin_unlock(&ip->i_flags_lock); - write_unlock(&ih->ih_lock); + write_unlock(&pag->pag_ici_lock); if (locked) { xfs_ifunlock(ip); xfs_iunlock(ip, XFS_ILOCK_EXCL); @@ -3951,7 +3745,8 @@ xfs_finish_reclaim( } __xfs_iflags_set(ip, XFS_IRECLAIM); spin_unlock(&ip->i_flags_lock); - write_unlock(&ih->ih_lock); + write_unlock(&pag->pag_ici_lock); + xfs_put_perag(ip->i_mount, pag); /* * If the inode is still dirty, then flush it out. If the inode @@ -4085,7 +3880,7 @@ xfs_alloc_file_space( int committed; int error; - vn_trace_entry(XFS_ITOV(ip), __FUNCTION__, (inst_t *)__return_address); + vn_trace_entry(ip, __FUNCTION__, (inst_t *)__return_address); if (XFS_FORCED_SHUTDOWN(mp)) return XFS_ERROR(EIO); @@ -4109,7 +3904,7 @@ xfs_alloc_file_space( /* Generate a DMAPI event if needed. */ if (alloc_type != 0 && offset < ip->i_size && (attr_flags&ATTR_DMI) == 0 && - DM_EVENT_ENABLED(XFS_MTOVFS(mp), ip, DM_EVENT_WRITE)) { + DM_EVENT_ENABLED(ip, DM_EVENT_WRITE)) { xfs_off_t end_dmi_offset; end_dmi_offset = offset+len; @@ -4223,9 +4018,8 @@ retry: allocatesize_fsb -= allocated_fsb; } dmapi_enospc_check: - if (error == ENOSPC && (attr_flags&ATTR_DMI) == 0 && - DM_EVENT_ENABLED(XFS_MTOVFS(mp), ip, DM_EVENT_NOSPACE)) { - + if (error == ENOSPC && (attr_flags & ATTR_DMI) == 0 && + DM_EVENT_ENABLED(ip, DM_EVENT_NOSPACE)) { error = XFS_SEND_NAMESP(mp, DM_EVENT_NOSPACE, XFS_ITOV(ip), DM_RIGHT_NULL, XFS_ITOV(ip), DM_RIGHT_NULL, @@ -4356,7 +4150,7 @@ xfs_free_file_space( vp = XFS_ITOV(ip); mp = ip->i_mount; - vn_trace_entry(vp, __FUNCTION__, (inst_t *)__return_address); + vn_trace_entry(ip, __FUNCTION__, (inst_t *)__return_address); if ((error = XFS_QM_DQATTACH(mp, ip, 0))) return error; @@ -4369,9 +4163,8 @@ xfs_free_file_space( end_dmi_offset = offset + len; endoffset_fsb = XFS_B_TO_FSBT(mp, end_dmi_offset); - if (offset < ip->i_size && - (attr_flags & ATTR_DMI) == 0 && - DM_EVENT_ENABLED(XFS_MTOVFS(mp), ip, DM_EVENT_WRITE)) { + if (offset < ip->i_size && (attr_flags & ATTR_DMI) == 0 && + DM_EVENT_ENABLED(ip, DM_EVENT_WRITE)) { if (end_dmi_offset > ip->i_size) end_dmi_offset = ip->i_size; error = XFS_SEND_DATA(mp, DM_EVENT_WRITE, vp, @@ -4385,7 +4178,7 @@ xfs_free_file_space( need_iolock = 0; if (need_iolock) { xfs_ilock(ip, XFS_IOLOCK_EXCL); - vn_iowait(vp); /* wait for the completion of any pending DIOs */ + vn_iowait(ip); /* wait for the completion of any pending DIOs */ } rounding = max_t(uint, 1 << mp->m_sb.sb_blocklog, NBPP); @@ -4394,7 +4187,8 @@ xfs_free_file_space( if (VN_CACHED(vp) != 0) { xfs_inval_cached_trace(&ip->i_iocore, ioffset, -1, ctooff(offtoct(ioffset)), -1); - error = bhv_vop_flushinval_pages(vp, ctooff(offtoct(ioffset)), + error = xfs_flushinval_pages(ip, + ctooff(offtoct(ioffset)), -1, FI_REMAPF_LOCKED); if (error) goto out_unlock_iolock; @@ -4545,35 +4339,29 @@ xfs_free_file_space( */ int xfs_change_file_space( - bhv_desc_t *bdp, + xfs_inode_t *ip, int cmd, xfs_flock64_t *bf, xfs_off_t offset, cred_t *credp, int attr_flags) { + xfs_mount_t *mp = ip->i_mount; int clrprealloc; int error; xfs_fsize_t fsize; - xfs_inode_t *ip; - xfs_mount_t *mp; int setprealloc; xfs_off_t startoffset; xfs_off_t llen; xfs_trans_t *tp; bhv_vattr_t va; - bhv_vnode_t *vp; - vp = BHV_TO_VNODE(bdp); - vn_trace_entry(vp, __FUNCTION__, (inst_t *)__return_address); - - ip = XFS_BHVTOI(bdp); - mp = ip->i_mount; + vn_trace_entry(ip, __FUNCTION__, (inst_t *)__return_address); /* * must be a regular file and have write permission */ - if (!VN_ISREG(vp)) + if (!S_ISREG(ip->i_d.di_mode)) return XFS_ERROR(EINVAL); xfs_ilock(ip, XFS_ILOCK_SHARED); @@ -4655,7 +4443,7 @@ xfs_change_file_space( va.va_mask = XFS_AT_SIZE; va.va_size = startoffset; - error = xfs_setattr(bdp, &va, attr_flags, credp); + error = xfs_setattr(ip, &va, attr_flags, credp); if (error) return error; @@ -4714,46 +4502,3 @@ xfs_change_file_space( return error; } - -bhv_vnodeops_t xfs_vnodeops = { - BHV_IDENTITY_INIT(VN_BHV_XFS,VNODE_POSITION_XFS), - .vop_open = xfs_open, - .vop_read = xfs_read, -#ifdef HAVE_SPLICE - .vop_splice_read = xfs_splice_read, - .vop_splice_write = xfs_splice_write, -#endif - .vop_write = xfs_write, - .vop_ioctl = xfs_ioctl, - .vop_getattr = xfs_getattr, - .vop_setattr = xfs_setattr, - .vop_access = xfs_access, - .vop_lookup = xfs_lookup, - .vop_create = xfs_create, - .vop_remove = xfs_remove, - .vop_link = xfs_link, - .vop_rename = xfs_rename, - .vop_mkdir = xfs_mkdir, - .vop_rmdir = xfs_rmdir, - .vop_readdir = xfs_readdir, - .vop_symlink = xfs_symlink, - .vop_readlink = xfs_readlink, - .vop_fsync = xfs_fsync, - .vop_inactive = xfs_inactive, - .vop_fid2 = xfs_fid2, - .vop_rwlock = xfs_rwlock, - .vop_rwunlock = xfs_rwunlock, - .vop_bmap = xfs_bmap, - .vop_reclaim = xfs_reclaim, - .vop_attr_get = xfs_attr_get, - .vop_attr_set = xfs_attr_set, - .vop_attr_remove = xfs_attr_remove, - .vop_attr_list = xfs_attr_list, - .vop_link_removed = (vop_link_removed_t)fs_noval, - .vop_vnode_change = (vop_vnode_change_t)fs_noval, - .vop_tosspages = fs_tosspages, - .vop_flushinval_pages = fs_flushinval_pages, - .vop_flush_pages = fs_flush_pages, - .vop_release = xfs_release, - .vop_iflush = xfs_inode_flush, -}; diff --git a/fs/xfs/xfs_vnodeops.h b/fs/xfs/xfs_vnodeops.h new file mode 100644 index 000000000000..f36e74f2f0c2 --- /dev/null +++ b/fs/xfs/xfs_vnodeops.h @@ -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 */ |