Commit 87129d96 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
parents 55faed1e cde410a9
#
# Copyright (c) 2000-2004 Silicon Graphics, Inc. All Rights Reserved.
#
# This program is free software; you can redistribute it and/or modify it
# under the terms of version 2 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.
#
# Further, this software is distributed without any warranty that it is
# free of the rightful claim of any third person regarding infringement
# or the like. Any license provided herein, whether implied or
# otherwise, applies only to this software file. Patent licenses, if
# any, provided herein do not apply to combinations of this program with
# other software, or any other product whatsoever.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, write the Free Software Foundation, Inc., 59
# Temple Place - Suite 330, Boston MA 02111-1307, USA.
#
# Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
# Mountain View, CA 94043, or:
#
# http://www.sgi.com
#
# For further information regarding this notice, see:
#
# http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
#
EXTRA_CFLAGS += -Ifs/xfs -Ifs/xfs/linux-2.6 -funsigned-char
ifeq ($(CONFIG_XFS_DEBUG),y)
EXTRA_CFLAGS += -g -DSTATIC="" -DDEBUG
EXTRA_CFLAGS += -DPAGEBUF_LOCK_TRACKING
endif
ifeq ($(CONFIG_XFS_TRACE),y)
EXTRA_CFLAGS += -DXFS_ALLOC_TRACE
EXTRA_CFLAGS += -DXFS_ATTR_TRACE
EXTRA_CFLAGS += -DXFS_BLI_TRACE
EXTRA_CFLAGS += -DXFS_BMAP_TRACE
EXTRA_CFLAGS += -DXFS_BMBT_TRACE
EXTRA_CFLAGS += -DXFS_DIR_TRACE
EXTRA_CFLAGS += -DXFS_DIR2_TRACE
EXTRA_CFLAGS += -DXFS_DQUOT_TRACE
EXTRA_CFLAGS += -DXFS_ILOCK_TRACE
EXTRA_CFLAGS += -DXFS_LOG_TRACE
EXTRA_CFLAGS += -DXFS_RW_TRACE
EXTRA_CFLAGS += -DPAGEBUF_TRACE
EXTRA_CFLAGS += -DXFS_VNODE_TRACE
endif
obj-$(CONFIG_XFS_FS) += xfs.o
xfs-$(CONFIG_XFS_QUOTA) += $(addprefix quota/, \
xfs_dquot.o \
xfs_dquot_item.o \
xfs_trans_dquot.o \
xfs_qm_syscalls.o \
xfs_qm_bhv.o \
xfs_qm.o)
ifeq ($(CONFIG_XFS_QUOTA),y)
xfs-$(CONFIG_PROC_FS) += quota/xfs_qm_stats.o
endif
xfs-$(CONFIG_XFS_RT) += xfs_rtalloc.o
xfs-$(CONFIG_XFS_POSIX_ACL) += xfs_acl.o
xfs-$(CONFIG_PROC_FS) += linux-2.6/xfs_stats.o
xfs-$(CONFIG_SYSCTL) += linux-2.6/xfs_sysctl.o
xfs-$(CONFIG_COMPAT) += linux-2.6/xfs_ioctl32.o
xfs-$(CONFIG_XFS_EXPORT) += linux-2.6/xfs_export.o
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 \
xfs_btree.o \
xfs_buf_item.o \
xfs_da_btree.o \
xfs_dir.o \
xfs_dir2.o \
xfs_dir2_block.o \
xfs_dir2_data.o \
xfs_dir2_leaf.o \
xfs_dir2_node.o \
xfs_dir2_sf.o \
xfs_dir_leaf.o \
xfs_error.o \
xfs_extfree_item.o \
xfs_fsops.o \
xfs_ialloc.o \
xfs_ialloc_btree.o \
xfs_iget.o \
xfs_inode.o \
xfs_inode_item.o \
xfs_iocore.o \
xfs_iomap.o \
xfs_itable.o \
xfs_dfrag.o \
xfs_log.o \
xfs_log_recover.o \
xfs_macros.o \
xfs_mount.o \
xfs_rename.o \
xfs_trans.o \
xfs_trans_ail.o \
xfs_trans_buf.o \
xfs_trans_extfree.o \
xfs_trans_inode.o \
xfs_trans_item.o \
xfs_utils.o \
xfs_vfsops.o \
xfs_vnodeops.o \
xfs_rw.o \
xfs_dmops.o \
xfs_qmops.o
xfs-$(CONFIG_XFS_TRACE) += xfs_dir2_trace.o
# Objects in linux-2.6/
xfs-y += $(addprefix linux-2.6/, \
kmem.o \
xfs_aops.o \
xfs_buf.o \
xfs_file.o \
xfs_fs_subr.o \
xfs_globals.o \
xfs_ioctl.o \
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 \
qsort.o \
uuid.o)
xfs-$(CONFIG_XFS_TRACE) += support/ktrace.o
include $(TOPDIR)/fs/xfs/Makefile-linux-$(VERSION).$(PATCHLEVEL)
#
# Copyright (c) 2000-2004 Silicon Graphics, Inc. All Rights Reserved.
#
# This program is free software; you can redistribute it and/or modify it
# under the terms of version 2 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.
#
# Further, this software is distributed without any warranty that it is
# free of the rightful claim of any third person regarding infringement
# or the like. Any license provided herein, whether implied or
# otherwise, applies only to this software file. Patent licenses, if
# any, provided herein do not apply to combinations of this program with
# other software, or any other product whatsoever.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, write the Free Software Foundation, Inc., 59
# Temple Place - Suite 330, Boston MA 02111-1307, USA.
#
# Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
# Mountain View, CA 94043, or:
#
# http://www.sgi.com
#
# For further information regarding this notice, see:
#
# http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
#
EXTRA_CFLAGS += -Ifs/xfs -Ifs/xfs/linux-2.6 -funsigned-char
XFS_LINUX := linux-2.6
ifeq ($(CONFIG_XFS_DEBUG),y)
EXTRA_CFLAGS += -g -DSTATIC="" -DDEBUG
EXTRA_CFLAGS += -DPAGEBUF_LOCK_TRACKING
endif
ifeq ($(CONFIG_XFS_TRACE),y)
EXTRA_CFLAGS += -DXFS_ALLOC_TRACE
EXTRA_CFLAGS += -DXFS_ATTR_TRACE
EXTRA_CFLAGS += -DXFS_BLI_TRACE
EXTRA_CFLAGS += -DXFS_BMAP_TRACE
EXTRA_CFLAGS += -DXFS_BMBT_TRACE
EXTRA_CFLAGS += -DXFS_DIR_TRACE
EXTRA_CFLAGS += -DXFS_DIR2_TRACE
EXTRA_CFLAGS += -DXFS_DQUOT_TRACE
EXTRA_CFLAGS += -DXFS_ILOCK_TRACE
EXTRA_CFLAGS += -DXFS_LOG_TRACE
EXTRA_CFLAGS += -DXFS_RW_TRACE
EXTRA_CFLAGS += -DPAGEBUF_TRACE
EXTRA_CFLAGS += -DXFS_VNODE_TRACE
endif
obj-$(CONFIG_XFS_FS) += xfs.o
obj-$(CONFIG_XFS_QUOTA) += quota/
xfs-$(CONFIG_XFS_RT) += xfs_rtalloc.o
xfs-$(CONFIG_XFS_POSIX_ACL) += xfs_acl.o
xfs-$(CONFIG_PROC_FS) += $(XFS_LINUX)/xfs_stats.o
xfs-$(CONFIG_SYSCTL) += $(XFS_LINUX)/xfs_sysctl.o
xfs-$(CONFIG_COMPAT) += $(XFS_LINUX)/xfs_ioctl32.o
xfs-$(CONFIG_XFS_EXPORT) += $(XFS_LINUX)/xfs_export.o
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 \
xfs_btree.o \
xfs_buf_item.o \
xfs_da_btree.o \
xfs_dir.o \
xfs_dir2.o \
xfs_dir2_block.o \
xfs_dir2_data.o \
xfs_dir2_leaf.o \
xfs_dir2_node.o \
xfs_dir2_sf.o \
xfs_dir_leaf.o \
xfs_error.o \
xfs_extfree_item.o \
xfs_fsops.o \
xfs_ialloc.o \
xfs_ialloc_btree.o \
xfs_iget.o \
xfs_inode.o \
xfs_inode_item.o \
xfs_iocore.o \
xfs_iomap.o \
xfs_itable.o \
xfs_dfrag.o \
xfs_log.o \
xfs_log_recover.o \
xfs_macros.o \
xfs_mount.o \
xfs_rename.o \
xfs_trans.o \
xfs_trans_ail.o \
xfs_trans_buf.o \
xfs_trans_extfree.o \
xfs_trans_inode.o \
xfs_trans_item.o \
xfs_utils.o \
xfs_vfsops.o \
xfs_vnodeops.o \
xfs_rw.o \
xfs_dmops.o \
xfs_qmops.o
xfs-$(CONFIG_XFS_TRACE) += xfs_dir2_trace.o
# Objects in linux/
xfs-y += $(addprefix $(XFS_LINUX)/, \
kmem.o \
xfs_aops.o \
xfs_buf.o \
xfs_file.o \
xfs_fs_subr.o \
xfs_globals.o \
xfs_ioctl.o \
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
......@@ -45,11 +45,11 @@
void *
kmem_alloc(size_t size, int flags)
kmem_alloc(size_t size, unsigned int __nocast flags)
{
int retries = 0;
int lflags = kmem_flags_convert(flags);
void *ptr;
int retries = 0;
unsigned int lflags = kmem_flags_convert(flags);
void *ptr;
do {
if (size < MAX_SLAB_SIZE || retries > MAX_VMALLOCS)
......@@ -67,7 +67,7 @@ kmem_alloc(size_t size, int flags)
}
void *
kmem_zalloc(size_t size, int flags)
kmem_zalloc(size_t size, unsigned int __nocast flags)
{
void *ptr;
......@@ -89,7 +89,8 @@ kmem_free(void *ptr, size_t size)
}
void *
kmem_realloc(void *ptr, size_t newsize, size_t oldsize, int flags)
kmem_realloc(void *ptr, size_t newsize, size_t oldsize,
unsigned int __nocast flags)
{
void *new;
......@@ -104,11 +105,11 @@ kmem_realloc(void *ptr, size_t newsize, size_t oldsize, int flags)
}
void *
kmem_zone_alloc(kmem_zone_t *zone, int flags)
kmem_zone_alloc(kmem_zone_t *zone, unsigned int __nocast flags)
{
int retries = 0;
int lflags = kmem_flags_convert(flags);
void *ptr;
int retries = 0;
unsigned int lflags = kmem_flags_convert(flags);
void *ptr;
do {
ptr = kmem_cache_alloc(zone, lflags);
......@@ -123,7 +124,7 @@ kmem_zone_alloc(kmem_zone_t *zone, int flags)
}
void *
kmem_zone_zalloc(kmem_zone_t *zone, int flags)
kmem_zone_zalloc(kmem_zone_t *zone, unsigned int __nocast flags)
{
void *ptr;
......
......@@ -39,10 +39,10 @@
/*
* memory management routines
*/
#define KM_SLEEP 0x0001
#define KM_NOSLEEP 0x0002
#define KM_NOFS 0x0004
#define KM_MAYFAIL 0x0008
#define KM_SLEEP 0x0001u
#define KM_NOSLEEP 0x0002u
#define KM_NOFS 0x0004u
#define KM_MAYFAIL 0x0008u
#define kmem_zone kmem_cache_s
#define kmem_zone_t kmem_cache_t
......@@ -81,9 +81,9 @@ typedef unsigned long xfs_pflags_t;
*(NSTATEP) = *(OSTATEP); \
} while (0)
static __inline unsigned int kmem_flags_convert(int flags)
static __inline unsigned int kmem_flags_convert(unsigned int __nocast flags)
{
int lflags = __GFP_NOWARN; /* we'll report problems, if need be */
unsigned int lflags = __GFP_NOWARN; /* we'll report problems, if need be */
#ifdef DEBUG
if (unlikely(flags & ~(KM_SLEEP|KM_NOSLEEP|KM_NOFS|KM_MAYFAIL))) {
......@@ -125,12 +125,13 @@ kmem_zone_destroy(kmem_zone_t *zone)
BUG();
}
extern void *kmem_zone_zalloc(kmem_zone_t *, int);
extern void *kmem_zone_alloc(kmem_zone_t *, int);
extern void *kmem_zone_zalloc(kmem_zone_t *, unsigned int __nocast);
extern void *kmem_zone_alloc(kmem_zone_t *, unsigned int __nocast);
extern void *kmem_alloc(size_t, int);
extern void *kmem_realloc(void *, size_t, size_t, int);
extern void *kmem_zalloc(size_t, int);
extern void *kmem_alloc(size_t, unsigned int __nocast);
extern void *kmem_realloc(void *, size_t, size_t,
unsigned int __nocast);
extern void *kmem_zalloc(size_t, unsigned int __nocast);
extern void kmem_free(void *, size_t);
typedef struct shrinker *kmem_shaker_t;
......
......@@ -45,6 +45,9 @@
typedef spinlock_t lock_t;
#define SPLDECL(s) unsigned long s
#ifndef DEFINE_SPINLOCK
#define DEFINE_SPINLOCK(s) spinlock_t s = SPIN_LOCK_UNLOCKED
#endif
#define spinlock_init(lock, name) spin_lock_init(lock)
#define spinlock_destroy(lock)
......
......@@ -104,66 +104,114 @@ xfs_page_trace(
#define xfs_page_trace(tag, inode, page, mask)
#endif
void
linvfs_unwritten_done(
struct buffer_head *bh,
int uptodate)
/*
* Schedule IO completion handling on a xfsdatad if this was
* the final hold on this ioend.
*/
STATIC void
xfs_finish_ioend(
xfs_ioend_t *ioend)
{
xfs_buf_t *pb = (xfs_buf_t *)bh->b_private;
if (atomic_dec_and_test(&ioend->io_remaining))
queue_work(xfsdatad_workqueue, &ioend->io_work);
}
ASSERT(buffer_unwritten(bh));
bh->b_end_io = NULL;
clear_buffer_unwritten(bh);
if (!uptodate)
pagebuf_ioerror(pb, EIO);
if (atomic_dec_and_test(&pb->pb_io_remaining) == 1) {
pagebuf_iodone(pb, 1, 1);
}
end_buffer_async_write(bh, uptodate);
STATIC void
xfs_destroy_ioend(
xfs_ioend_t *ioend)
{
vn_iowake(ioend->io_vnode);
mempool_free(ioend, xfs_ioend_pool);
}
/*
* Issue transactions to convert a buffer range from unwritten
* to written extents (buffered IO).
* to written extents.
*/
STATIC void
linvfs_unwritten_convert(
xfs_buf_t *bp)
xfs_end_bio_unwritten(
void *data)
{
vnode_t *vp = XFS_BUF_FSPRIVATE(bp, vnode_t *);
int error;
xfs_ioend_t *ioend = data;
vnode_t *vp = ioend->io_vnode;
xfs_off_t offset = ioend->io_offset;
size_t size = ioend->io_size;
struct buffer_head *bh, *next;
int error;
if (ioend->io_uptodate)
VOP_BMAP(vp, offset, size, BMAPI_UNWRITTEN, NULL, NULL, error);
/* ioend->io_buffer_head is only non-NULL for buffered I/O */
for (bh = ioend->io_buffer_head; bh; bh = next) {
next = bh->b_private;
bh->b_end_io = NULL;
clear_buffer_unwritten(bh);
end_buffer_async_write(bh, ioend->io_uptodate);
}
BUG_ON(atomic_read(&bp->pb_hold) < 1);
VOP_BMAP(vp, XFS_BUF_OFFSET(bp), XFS_BUF_SIZE(bp),
BMAPI_UNWRITTEN, NULL, NULL, error);
XFS_BUF_SET_FSPRIVATE(bp, NULL);
XFS_BUF_CLR_IODONE_FUNC(bp);
XFS_BUF_UNDATAIO(bp);
iput(LINVFS_GET_IP(vp));
pagebuf_iodone(bp, 0, 0);
xfs_destroy_ioend(ioend);
}
/*
* Issue transactions to convert a buffer range from unwritten
* to written extents (direct IO).
* Allocate and initialise an IO completion structure.
* We need to track unwritten extent write completion here initially.
* We'll need to extend this for updating the ondisk inode size later
* (vs. incore size).
*/
STATIC void
linvfs_unwritten_convert_direct(
struct kiocb *iocb,
loff_t offset,
ssize_t size,
void *private)
STATIC xfs_ioend_t *
xfs_alloc_ioend(
struct inode *inode)
{
struct inode *inode = iocb->ki_filp->f_dentry->d_inode;
ASSERT(!private || inode == (struct inode *)private);
xfs_ioend_t *ioend;
/* private indicates an unwritten extent lay beneath this IO */
if (private && size > 0) {
vnode_t *vp = LINVFS_GET_VP(inode);
int error;
ioend = mempool_alloc(xfs_ioend_pool, GFP_NOFS);
VOP_BMAP(vp, offset, size, BMAPI_UNWRITTEN, NULL, NULL, error);
}
/*
* Set the count to 1 initially, which will prevent an I/O
* completion callback from happening before we have started
* all the I/O from calling the completion routine too early.
*/
atomic_set(&ioend->io_remaining, 1);
ioend->io_uptodate = 1; /* cleared if any I/O fails */
ioend->io_vnode = LINVFS_GET_VP(inode);
ioend->io_buffer_head = NULL;
atomic_inc(&ioend->io_vnode->v_iocount);
ioend->io_offset = 0;
ioend->io_size = 0;
INIT_WORK(&ioend->io_work, xfs_end_bio_unwritten, ioend);
return ioend;
}
void
linvfs_unwritten_done(
struct buffer_head *bh,
int uptodate)
{
xfs_ioend_t *ioend = bh->b_private;
static spinlock_t unwritten_done_lock = SPIN_LOCK_UNLOCKED;
unsigned long flags;
ASSERT(buffer_unwritten(bh));
bh->b_end_io = NULL;
if (!uptodate)
ioend->io_uptodate = 0;
/*
* Deep magic here. We reuse b_private in the buffer_heads to build
* a chain for completing the I/O from user context after we've issued
* a transaction to convert the unwritten extent.
*/
spin_lock_irqsave(&unwritten_done_lock, flags);
bh->b_private = ioend->io_buffer_head;
ioend->io_buffer_head = bh;
spin_unlock_irqrestore(&unwritten_done_lock, flags);
xfs_finish_ioend(ioend);
}
STATIC int
......@@ -255,7 +303,7 @@ xfs_probe_unwritten_page(
struct address_space *mapping,
pgoff_t index,
xfs_iomap_t *iomapp,
xfs_buf_t *pb,
xfs_ioend_t *ioend,
unsigned long max_offset,
unsigned long *fsbs,
unsigned int bbits)
......@@ -283,7 +331,7 @@ xfs_probe_unwritten_page(
break;
xfs_map_at_offset(page, bh, p_offset, bbits, iomapp);
set_buffer_unwritten_io(bh);
bh->b_private = pb;
bh->b_private = ioend;
p_offset += bh->b_size;
(*fsbs)++;
} while ((bh = bh->b_this_page) != head);
......@@ -434,34 +482,15 @@ xfs_map_unwritten(
{
struct buffer_head *bh = curr;
xfs_iomap_t *tmp;
xfs_buf_t *pb;
loff_t offset, size;
xfs_ioend_t *ioend;
loff_t offset;
unsigned long nblocks = 0;
offset = start_page->index;
offset <<= PAGE_CACHE_SHIFT;
offset += p_offset;
/* get an "empty" pagebuf to manage IO completion
* Proper values will be set before returning */
pb = pagebuf_lookup(iomapp->iomap_target, 0, 0, 0);
if (!pb)
return -EAGAIN;
/* Take a reference to the inode to prevent it from
* being reclaimed while we have outstanding unwritten
* extent IO on it.
*/
if ((igrab(inode)) != inode) {
pagebuf_free(pb);
return -EAGAIN;
}
/* Set the count to 1 initially, this will stop an I/O
* completion callout which happens before we have started
* all the I/O from calling pagebuf_iodone too early.
*/
atomic_set(&pb->pb_io_remaining, 1);
ioend = xfs_alloc_ioend(inode);
/* First map forwards in the page consecutive buffers
* covering this unwritten extent
......@@ -474,12 +503,12 @@ xfs_map_unwritten(
break;
xfs_map_at_offset(start_page, bh, p_offset, block_bits, iomapp);
set_buffer_unwritten_io(bh);
bh->b_private = pb;
bh->b_private = ioend;
p_offset += bh->b_size;
nblocks++;
} while ((bh = bh->b_this_page) != head);
atomic_add(nblocks, &pb->pb_io_remaining);
atomic_add(nblocks, &ioend->io_remaining);
/* If we reached the end of the page, map forwards in any
* following pages which are also covered by this extent.
......@@ -496,13 +525,13 @@ xfs_map_unwritten(
tloff = min(tlast, tloff);
for (tindex = start_page->index + 1; tindex < tloff; tindex++) {
page = xfs_probe_unwritten_page(mapping,