Commit 20d7d526 authored by Christoph Hellwig's avatar Christoph Hellwig

Merge

parents 7196d9df ef2ead69
......@@ -132,7 +132,6 @@ xfs-y += $(addprefix linux/, \
# Objects in support/
xfs-y += $(addprefix support/, \
debug.o \
kmem.o \
ktrace.o \
move.o \
mrlock.o \
......
......@@ -48,7 +48,7 @@ unsigned long xfs_physmem;
* Tunable XFS parameters. xfs_params is required even when CONFIG_SYSCTL=n,
* other XFS code uses these values.
*/
xfs_param_t xfs_params = { 0, 1, 0, 0, 0, 3 };
xfs_param_t xfs_params = { 0, 1, 0, 0, 0, 3, 30 * HZ };
/*
* Global system credential structure.
......
......@@ -152,8 +152,6 @@ linvfs_mknod(
ip->i_rdev = to_kdev_t(rdev);
validate_fields(dir);
d_instantiate(dentry, ip);
mark_inode_dirty_sync(ip);
mark_inode_dirty_sync(dir);
}
if (!error && have_default_acl) {
......@@ -240,7 +238,6 @@ linvfs_link(
VN_HOLD(vp);
validate_fields(ip);
d_instantiate(dentry, ip);
mark_inode_dirty_sync(ip);
}
return -error;
}
......@@ -261,8 +258,6 @@ linvfs_unlink(
if (!error) {
validate_fields(dir); /* For size only */
validate_fields(inode);
mark_inode_dirty_sync(inode);
mark_inode_dirty_sync(dir);
}
return -error;
......@@ -296,8 +291,6 @@ linvfs_symlink(
d_instantiate(dentry, ip);
validate_fields(dir);
validate_fields(ip); /* size needs update */
mark_inode_dirty_sync(ip);
mark_inode_dirty_sync(dir);
}
return -error;
}
......@@ -315,8 +308,6 @@ linvfs_rmdir(
if (!error) {
validate_fields(inode);
validate_fields(dir);
mark_inode_dirty_sync(inode);
mark_inode_dirty_sync(dir);
}
return -error;
}
......@@ -346,7 +337,6 @@ linvfs_rename(
validate_fields(odir);
if (ndir != odir)
validate_fields(ndir);
mark_inode_dirty(ndir);
return 0;
}
......@@ -520,7 +510,6 @@ linvfs_setattr(
if (!error) {
vn_revalidate(vp);
mark_inode_dirty_sync(inode);
}
return error;
}
......
......@@ -887,29 +887,23 @@ xfsbdstrat(
return (xfs_bioerror_relse(bp));
}
void
XFS_bflush(xfs_buftarg_t *target)
{
pagebuf_delwri_flush(target, PBDF_WAIT, NULL);
}
/*
* If the underlying (log or data) device is readonly, there are some
* If the underlying (data/log/rt) device is readonly, there are some
* operations that cannot proceed.
*/
int
xfs_dev_is_read_only(xfs_mount_t *mp, char *message)
xfs_dev_is_read_only(
xfs_mount_t *mp,
char *message)
{
if (bdev_read_only(mp->m_ddev_targp->pbr_bdev) ||
bdev_read_only(mp->m_logdev_targp->pbr_bdev) ||
(mp->m_rtdev_targp && bdev_read_only(mp->m_rtdev_targp->pbr_bdev))) {
if (xfs_readonly_buftarg(mp->m_ddev_targp) ||
xfs_readonly_buftarg(mp->m_logdev_targp) ||
(mp->m_rtdev_targp && xfs_readonly_buftarg(mp->m_rtdev_targp))) {
cmn_err(CE_NOTE,
"XFS: %s required on read-only device.", message);
cmn_err(CE_NOTE,
"XFS: write access unavailable, cannot proceed.");
return EROFS;
}
return 0;
}
......@@ -217,13 +217,27 @@ xfs_blkdev_put(
}
void
xfs_free_buftarg(
xfs_flush_buftarg(
xfs_buftarg_t *btp)
{
pagebuf_delwri_flush(btp, PBDF_WAIT, NULL);
}
void
xfs_free_buftarg(
xfs_buftarg_t *btp)
{
xfs_flush_buftarg(btp);
kmem_free(btp, sizeof(*btp));
}
int
xfs_readonly_buftarg(
xfs_buftarg_t *btp)
{
return bdev_read_only(btp->pbr_bdev);
}
void
xfs_relse_buftarg(
xfs_buftarg_t *btp)
......@@ -331,9 +345,10 @@ destroy_inodecache( void )
}
/*
* We do not actually write the inode here, just mark the
* super block dirty so that sync_supers calls us and
* forces the flush.
* Attempt to flush the inode, this will actually fail
* if the inode is pinned, but we dirty the inode again
* at the point when it is unpinned after a log write,
* since this is when the inode itself becomes flushable.
*/
STATIC void
linvfs_write_inode(
......@@ -348,8 +363,6 @@ linvfs_write_inode(
if (sync)
flags |= FLUSH_SYNC;
VOP_IFLUSH(vp, flags, error);
if (error == EAGAIN)
inode->i_sb->s_dirt = 1;
}
}
......@@ -369,6 +382,61 @@ linvfs_clear_inode(
}
}
#define SYNCD_FLAGS (SYNC_FSDATA|SYNC_BDFLUSH|SYNC_ATTR)
STATIC int
syncd(void *arg)
{
vfs_t *vfsp = (vfs_t *) arg;
int error;
daemonize("xfs_syncd");
vfsp->vfs_sync_task = current;
wmb();
wake_up(&vfsp->vfs_wait_sync_task);
for (;;) {
set_current_state(TASK_INTERRUPTIBLE);
schedule_timeout(xfs_params.sync_interval);
if (vfsp->vfs_flag & VFS_UMOUNT)
break;
if (vfsp->vfs_flag & VFS_RDONLY)
continue;
VFS_SYNC(vfsp, SYNCD_FLAGS, NULL, error);
}
vfsp->vfs_sync_task = NULL;
wmb();
wake_up(&vfsp->vfs_wait_sync_task);
return 0;
}
STATIC int
linvfs_start_syncd(vfs_t *vfsp)
{
int pid;
pid = kernel_thread(syncd, (void *) vfsp,
CLONE_VM | CLONE_FS | CLONE_FILES);
if (pid < 0)
return pid;
wait_event(vfsp->vfs_wait_sync_task, vfsp->vfs_sync_task);
return 0;
}
STATIC void
linvfs_stop_syncd(vfs_t *vfsp)
{
vfsp->vfs_flag |= VFS_UMOUNT;
wmb();
wake_up_process(vfsp->vfs_sync_task);
wait_event(vfsp->vfs_wait_sync_task, !vfsp->vfs_sync_task);
}
STATIC void
linvfs_put_super(
struct super_block *sb)
......@@ -376,8 +444,9 @@ linvfs_put_super(
vfs_t *vfsp = LINVFS_GET_VFS(sb);
int error;
linvfs_stop_syncd(vfsp);
VFS_SYNC(vfsp, SYNC_ATTR|SYNC_DELWRI, NULL, error);
if (error == 0)
if (!error)
VFS_UNMOUNT(vfsp, 0, NULL, error);
if (error) {
printk("XFS unmount got error %d\n", error);
......@@ -395,10 +464,13 @@ linvfs_write_super(
vfs_t *vfsp = LINVFS_GET_VFS(sb);
int error;
sb->s_dirt = 0;
if (sb->s_flags & MS_RDONLY)
if (sb->s_flags & MS_RDONLY) {
sb->s_dirt = 0; /* paranoia */
return;
VFS_SYNC(vfsp, SYNC_FSDATA|SYNC_BDFLUSH|SYNC_ATTR, NULL, error);
}
/* Push the log and superblock a little */
VFS_SYNC(vfsp, SYNC_FSDATA, NULL, error);
sb->s_dirt = 0;
}
STATIC int
......@@ -424,12 +496,8 @@ linvfs_remount(
int error;
VFS_PARSEARGS(vfsp, options, args, 1, error);
if (error)
goto out;
if (!error)
VFS_MNTUPDATE(vfsp, flags, args, error);
out:
kmem_free(args, sizeof(*args));
return error;
}
......@@ -438,11 +506,10 @@ STATIC void
linvfs_freeze_fs(
struct super_block *sb)
{
vfs_t *vfsp;
vfs_t *vfsp = LINVFS_GET_VFS(sb);
vnode_t *vp;
int error;
vfsp = LINVFS_GET_VFS(sb);
if (sb->s_flags & MS_RDONLY)
return;
VFS_ROOT(vfsp, &vp, error);
......@@ -454,11 +521,10 @@ STATIC void
linvfs_unfreeze_fs(
struct super_block *sb)
{
vfs_t *vfsp;
vfs_t *vfsp = LINVFS_GET_VFS(sb);
vnode_t *vp;
int error;
vfsp = LINVFS_GET_VFS(sb);
VFS_ROOT(vfsp, &vp, error);
VOP_IOCTL(vp, LINVFS_GET_IP(vp), NULL, XFS_IOC_THAW, 0, error);
VN_RELE(vp);
......@@ -652,7 +718,8 @@ linvfs_fill_super(
goto fail_vnrele;
if (is_bad_inode(sb->s_root->d_inode))
goto fail_vnrele;
if (linvfs_start_syncd(vfsp))
goto fail_vnrele;
vn_trace_exit(rootvp, __FUNCTION__, (inst_t *)__return_address);
kmem_free(args, sizeof(*args));
......
......@@ -101,7 +101,8 @@ extern void xfs_blkdev_put(struct block_device *);
extern struct pb_target *xfs_alloc_buftarg(struct block_device *);
extern void xfs_relse_buftarg(struct pb_target *);
extern void xfs_free_buftarg(struct pb_target *);
extern void xfs_flush_buftarg(struct pb_target *);
extern int xfs_readonly_buftarg(struct pb_target *);
extern void xfs_setsize_buftarg(struct pb_target *, unsigned int, unsigned int);
extern unsigned int xfs_getsize_buftarg(struct pb_target *);
......
/*
* Copyright (c) 2000-2003 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/
*/
#include <xfs.h>
#define SYNCD_FLAGS (SYNC_FSDATA|SYNC_BDFLUSH|SYNC_ATTR)
int syncd(void *arg)
{
vfs_t *vfsp = (vfs_t *) arg;
int error;
daemonize("xfs_syncd");
vfsp->vfs_sync_task = current;
wmb();
wake_up(&vfsp->vfs_wait_sync_task);
for (;;) {
set_current_state(TASK_INTERRUPTIBLE);
schedule_timeout(xfs_params.sync_interval);
if (vfsp->vfs_flag & VFS_UMOUNT)
break;
if (vfsp->vfs_flag & VFS_RDONLY);
continue;
VFS_SYNC(vfsp, SYNCD_FLAGS, NULL, error);
}
vfsp->vfs_sync_task = NULL;
wmb();
wake_up(&vfsp->vfs_wait_sync_task);
return 0;
}
int
linvfs_start_syncd(vfs_t *vfsp)
{
int pid;
pid = kernel_thread(syncd, (void *) vfsp,
CLONE_VM | CLONE_FS | CLONE_FILES);
if (pid < 0)
return pid;
wait_event(vfsp->vfs_wait_sync_task, vfsp->vfs_sync_task);
return 0;
}
void
linvfs_stop_syncd(vfs_t *vfsp)
{
vfsp->vfs_flag |= VFS_UMOUNT;
wmb();
wake_up_process(vfsp->vfs_sync_task);
wait_event(vfsp->vfs_wait_sync_task, !vfsp->vfs_sync_task);
}
......@@ -36,8 +36,8 @@
#include <linux/proc_fs.h>
STATIC ulong xfs_min[XFS_PARAM] = { 0, 0, 0, 0, 0, 0 };
STATIC ulong xfs_max[XFS_PARAM] = { 1, 1, 1, 1, 127, 3 };
STATIC ulong xfs_min[XFS_PARAM] = { 0, 0, 0, 0, 0, 0, HZ };
STATIC ulong xfs_max[XFS_PARAM] = { 1, 1, 1, 1, 127, 3, HZ * 60 };
static struct ctl_table_header *xfs_table_header;
......@@ -92,6 +92,10 @@ STATIC ctl_table xfs_table[] = {
sizeof(ulong), 0644, NULL, &proc_doulongvec_minmax,
&sysctl_intvec, NULL, &xfs_min[5], &xfs_max[5]},
{XFS_SYNC_INTERVAL, "sync_interval", &xfs_params.sync_interval,
sizeof(ulong), 0644, NULL, &proc_doulongvec_minmax,
&sysctl_intvec, NULL, &xfs_min[6], &xfs_max[6]},
{0}
};
......
......@@ -49,6 +49,7 @@ typedef struct xfs_param {
ulong symlink_mode; /* Symlink creat mode affected by umask. */
ulong panic_mask; /* bitmask to specify panics on errors. */
ulong error_level; /* Degree of reporting for internal probs*/
ulong sync_interval; /* time between sync calls */
} xfs_param_t;
/*
......@@ -73,6 +74,7 @@ enum {
XFS_SYMLINK_MODE = 4,
XFS_PANIC_MASK = 5,
XFS_ERRLEVEL = 6,
XFS_SYNC_INTERVAL = 7,
};
extern xfs_param_t xfs_params;
......
......@@ -238,6 +238,7 @@ vfs_allocate( void )
vfsp = kmem_zalloc(sizeof(vfs_t), KM_SLEEP);
bhv_head_init(VFS_BHVHEAD(vfsp), "vfs");
init_waitqueue_head(&vfsp->vfs_wait_sync_task);
return vfsp;
}
......
......@@ -48,6 +48,8 @@ typedef struct vfs {
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; /* Linux superblock structure */
struct task_struct *vfs_sync_task;
wait_queue_head_t vfs_wait_sync_task;
} vfs_t;
#define vfs_fbhv vfs_bh.bh_first /* 1st on vfs behavior chain */
......@@ -78,7 +80,8 @@ typedef enum {
#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 */
#define VFS_END 0x0004 /* max flag */
#define VFS_UMOUNT 0x0008 /* unmount in progress */
#define VFS_END 0x0008 /* max flag */
#define SYNC_ATTR 0x0001 /* sync attributes */
#define SYNC_CLOSE 0x0002 /* close file system down */
......@@ -87,6 +90,7 @@ typedef enum {
#define SYNC_FSDATA 0x0020 /* flush fs data (e.g. superblocks) */
#define SYNC_BDFLUSH 0x0010 /* BDFLUSH is calling -- don't block */
typedef int (*vfs_mount_t)(bhv_desc_t *,
struct xfs_mount_args *, struct cred *);
typedef int (*vfs_parseargs_t)(bhv_desc_t *, char *,
......
......@@ -562,8 +562,7 @@ static __inline__ void vn_flagclr(struct vnode *vp, uint flag)
(!list_empty(&(LINVFS_GET_IP(vp)->i_mapping->i_mmap_shared))))
#define VN_CACHED(vp) (LINVFS_GET_IP(vp)->i_mapping->nrpages)
#define VN_DIRTY(vp) (!list_empty(&(LINVFS_GET_IP(vp)->i_mapping->dirty_pages)))
#define VMODIFY(vp) { VN_FLAGSET(vp, VMODIFIED); \
mark_inode_dirty(LINVFS_GET_IP(vp)); }
#define VMODIFY(vp) VN_FLAGSET(vp, VMODIFIED)
#define VUNMODIFY(vp) VN_FLAGCLR(vp, VMODIFIED)
/*
......
......@@ -68,7 +68,7 @@
#define BN_ALIGN_MASK ((1 << (PAGE_CACHE_SHIFT - BBSHIFT)) - 1)
#ifndef GFP_READAHEAD
#define GFP_READAHEAD __GFP_NOWARN
#define GFP_READAHEAD (__GFP_NOWARN|__GFP_NORETRY)
#endif
/*
......@@ -181,7 +181,7 @@ _bhash(
* dev_t is 16 bits, loff_t is always 64 bits
*/
base ^= dev;
for (bit = hval = 0; base != 0 && bit < sizeof(base) * 8; bit += NBITS) {
for (bit = hval = 0; base && bit < sizeof(base) * 8; bit += NBITS) {
hval ^= (int)base & (NHASH-1);
base >>= NBITS;
}
......@@ -189,18 +189,18 @@ _bhash(
}
/*
* Mapping of multi-page buffers into contingous virtual space
* Mapping of multi-page buffers into contiguous virtual space
*/
STATIC void *pagebuf_mapout_locked(page_buf_t *);
STATIC spinlock_t as_lock = SPIN_LOCK_UNLOCKED;
typedef struct a_list {
void *vm_addr;
struct a_list *next;
} a_list_t;
STATIC a_list_t *as_free_head;
STATIC int as_list_len;
STATIC spinlock_t as_lock = SPIN_LOCK_UNLOCKED;
/*
......@@ -1897,13 +1897,6 @@ pagebuf_readstats(
}
#endif /* CONFIG_PROC_FS */
STATIC void
pagebuf_shaker(void)
{
pagebuf_daemon_wakeup(1);
}
/*
* Initialization and Termination
*/
......@@ -1943,7 +1936,6 @@ pagebuf_init(void)
#endif
pagebuf_daemon_start();
kmem_shake_register(pagebuf_shaker);
return 0;
}
......@@ -1959,7 +1951,6 @@ pagebuf_terminate(void)
pagebuf_daemon_stop();
kmem_cache_destroy(pagebuf_cache);
kmem_shake_deregister(pagebuf_shaker);
unregister_sysctl_table(pagebuf_table_header);
#ifdef CONFIG_PROC_FS
......
......@@ -88,7 +88,7 @@ STATIC void xfs_qm_list_destroy(xfs_dqlist_t *);
STATIC int xfs_qm_quotacheck(xfs_mount_t *);
STATIC int xfs_qm_init_quotainos(xfs_mount_t *);
STATIC void xfs_qm_shake(void);
STATIC int xfs_qm_shake(int, unsigned int);
#ifdef DEBUG
extern mutex_t qcheck_lock;
......@@ -112,6 +112,8 @@ extern mutex_t qcheck_lock;
#define XQM_LIST_PRINT(l, NXT, title) do { } while (0)
#endif
struct shrinker *xfs_qm_shrinker;
/*
* Initialize the XQM structure.
* Note that there is not one quota manager per file system.
......@@ -161,7 +163,7 @@ xfs_Gqm_init(void)
} else
xqm->qm_dqzone = qm_dqzone;
kmem_shake_register(xfs_qm_shake);
xfs_qm_shrinker = set_shrinker(DEFAULT_SEEKS, xfs_qm_shake);
/*
* The t_dqinfo portion of transactions.
......@@ -193,7 +195,8 @@ xfs_qm_destroy(
ASSERT(xqm != NULL);
ASSERT(xqm->qm_nrefs == 0);
kmem_shake_deregister(xfs_qm_shake);
remove_shrinker(xfs_qm_shrinker);
hsize = xqm->qm_dqhashmask + 1;
for (i = 0; i < hsize; i++) {
xfs_qm_list_destroy(&(xqm->qm_usr_dqhtable[i]));
......@@ -2088,7 +2091,7 @@ xfs_qm_shake_freelist(
xfs_dqunlock(dqp);
xfs_qm_freelist_unlock(xfs_Gqm);
if (++restarts >= XFS_QM_RECLAIM_MAX_RESTARTS)
return (nreclaimed != howmany);
goto out;
XQM_STATS_INC(xqmstats.xs_qm_dqwants);
goto tryagain;
}
......@@ -2163,7 +2166,7 @@ xfs_qm_shake_freelist(
XFS_DQ_HASH_UNLOCK(hash);
xfs_qm_freelist_unlock(xfs_Gqm);
if (++restarts >= XFS_QM_RECLAIM_MAX_RESTARTS)
return (nreclaimed != howmany);
goto out;
goto tryagain;
}
xfs_dqtrace_entry(dqp, "DQSHAKE: UNLINKING");
......@@ -2188,7 +2191,8 @@ xfs_qm_shake_freelist(
dqp = nextdqp;
}
xfs_qm_freelist_unlock(xfs_Gqm);
return (nreclaimed != howmany);
out:
return nreclaimed;
}
......@@ -2197,13 +2201,15 @@ xfs_qm_shake_freelist(
* running low.
*/
/* ARGSUSED */
STATIC void
xfs_qm_shake(void)
STATIC int
xfs_qm_shake(int nr_to_scan, unsigned int gfp_mask)
{
int ndqused, nfree, n;
if (!(gfp_mask & __GFP_WAIT))
return 0;
if (!xfs_Gqm)
return;
return 0;
nfree = xfs_Gqm->qm_dqfreelist.qh_nelems; /* free dquots */
/* incore dquots in all f/s's */
......@@ -2212,12 +2218,12 @@ xfs_qm_shake(void)
ASSERT(ndqused >= 0);
if (nfree <= ndqused && nfree < ndquot)
return;
return 0;
ndqused *= xfs_Gqm->qm_dqfree_ratio; /* target # of free dquots */
n = nfree - ndqused - ndquot; /* # over target */
(void) xfs_qm_shake_freelist(MAX(nfree, n));
return xfs_qm_shake_freelist(MAX(nfree, n));
}
......
......@@ -32,31 +32,118 @@
#ifndef __XFS_SUPPORT_KMEM_H__
#define __XFS_SUPPORT_KMEM_H__
#include <linux/mm.h>
#include <linux/highmem.h>
#include <linux/slab.h>
#include <linux/vmalloc.h>
/*
* memory management routines
* Cutoff point to use vmalloc instead of kmalloc.
*/
#define MAX_SLAB_SIZE 0x10000
/*
* XFS uses slightly different names for these due to the
* IRIX heritage.
*/
#define kmem_zone kmem_cache_s
#define kmem_zone_t kmem_cache_t
#define KM_SLEEP 0x0001
#define KM_NOSLEEP 0x0002
#define KM_NOFS 0x0004
#define kmem_zone kmem_cache_s
#define kmem_zone_t kmem_cache_t
extern kmem_zone_t *kmem_zone_init(int, char *);
extern void *kmem_zone_zalloc(kmem_zone_t *, int);
extern void *kmem_zone_alloc(kmem_zone_t *, int);
extern void kmem_zone_free(kmem_zone_t *, void *);
/*
* XXX get rid of the unconditional __GFP_NOFAIL by adding
* a KM_FAIL flag and using it where we're allowed to fail.
*/
static __inline unsigned int
flag_convert(int flags)
{
#if DEBUG
if (unlikely(flags & ~(KM_SLEEP|KM_NOSLEEP|KM_NOFS))) {
printk(KERN_WARNING
"XFS: memory allocation with wrong flags (%x)\n", flags);
BUG();
}
#endif
if (flags & KM_NOSLEEP)
return GFP_ATOMIC;
/* If we're in a transaction, FS activity is not ok */
else if ((current->flags & PF_FSTRANS) || (flags & KM_NOFS))
return GFP_NOFS | __GFP_NOFAIL;
return GFP_KERNEL | __GFP_NOFAIL;
}
static __inline void *
kmem_alloc(size_t size, int flags)
{
if (unlikely(MAX_SLAB_SIZE < size))
/* Avoid doing filesystem sensitive stuff to get this */
return __vmalloc(size, flag_convert(flags), PAGE_KERNEL);
return kmalloc(size, flag_convert(flags));
}
static __inline void *
kmem_zalloc(size_t size, int flags)
{
void *ptr = kmem_alloc(size, flags);
if (likely(ptr != NULL))
memset(ptr, 0, size);
return ptr;
}
static __inline void
kmem_free(void *ptr, size_t size)
{
if (unlikely((unsigned long)ptr < VMALLOC_START ||
(unsigned long)ptr >= VMALLOC_END))
kfree(ptr);
else
vfree(ptr);
}
static __inline void *
kmem_realloc(void *ptr, size_t newsize, size_t oldsize, int flags)
{
void *new = kmem_alloc(newsize, flags);
if (likely(ptr != NULL)) {
if (likely(new != NULL))
memcpy(new, ptr, min(oldsize, newsize));
kmem_free(ptr, oldsize);
}
return new;
}
static __inline kmem_zone_t *
kmem_zone_init(int size, char *zone_name)
{
return kmem_cache_create(zone_name, size, 0, 0, NULL, NULL);
}
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_free(void *, size_t);
static __inline void *
kmem_zone_alloc(kmem_zone_t *zone, int flags)
{
return kmem_cache_alloc(zone, flag_convert(flags));
}
typedef void (*kmem_shake_func_t)(void);
static __inline void *
kmem_zone_zalloc(kmem_zone_t *zone, int flags)
{
void *ptr = kmem_zone_alloc(zone, flags);
if (likely(ptr != NULL))
memset(ptr, 0, kmem_cache_size(zone));
return ptr;
}
extern void kmem_shake_register(kmem_shake_func_t);
extern void kmem_shake_deregister(kmem_shake_func_t);
static __inline void
kmem_zone_free(kmem_zone_t *zone, void *ptr)
{
kmem_cache_free(zone, ptr);
}
#endif /* __XFS_SUPPORT_KMEM_H__ */
/*
* Copyright (c) 2000-2002 Silicon Graphics, Inc. All Rights Reserved.
* Copyright (c) 2000-2003 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
......@@ -185,9 +185,8 @@ xfs_agblock_t xfs_agfl_block(struct xfs_mount *mp);
#endif
#define XFS_AGFL_SIZE(mp) ((mp)->m_sb.sb_sectsize / sizeof(xfs_agblock_t))
/* -- nathans TODO ... use of BBSIZE here - should be sector size -- */
typedef struct xfs_agfl {
xfs_agblock_t agfl_bno[BBSIZE/sizeof(xfs_agblock_t)];
xfs_agblock_t agfl_bno[1]; /* actually XFS_AGFL_SIZE(mp) */
} xfs_agfl_t;
/*
......
/*
* Copyright (c) 2000-2002 Silicon Graphics, Inc. All Rights Reserved.
* Copyright (c) 2000-2003 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
......@@ -283,7 +283,6 @@ static inline int XFS_bwrite(page_buf_t *pb)
return error;
}
#define XFS_bdwrite(pb) \
pagebuf_iostart(pb, PBF_DELWRI | PBF_ASYNC)
......@@ -307,15 +306,15 @@ static inline int xfs_bdwrite(void *mp, page_buf_t *bp)
* of its metadata.
*/
extern void XFS_bflush(xfs_buftarg_t *);
#define xfs_binval(buftarg) XFS_bflush(buftarg)
#define xfs_binval(buftarg) xfs_flush_buftarg(buftarg)
#define XFS_bflush(buftarg) xfs_flush_buftarg(buftarg)
#define xfs_incore_relse(buftarg,delwri_only,wait) \
xfs_relse_buftarg(buftarg)
#define xfs_baread(target, rablkno, ralen) \
pagebuf_readahead((target), (rablkno), \
(ralen), PBF_DONT_BLOCK)
pagebuf_readahead((target), (rablkno), (ralen), PBF_DONT_BLOCK)
#define XFS_getrbuf(sleep,mp) \
pagebuf_get_empty((mp)->m_ddev_targp)
......
......@@ -252,6 +252,11 @@ xfs_iget_core(
if (newnode) {
xfs_iocore_inode_reinit(ip);
}
XFS_MOUNT_ILOCK(mp);
list_del_init(&ip->i_reclaim);
XFS_MOUNT_IUNLOCK(mp);
vn_trace_exit(vp, "xfs_iget.found",
(inst_t *)__return_address);
goto return_ip;
......@@ -467,8 +472,10 @@ xfs_iget(
}
bdp = vn_bhv_lookup(VN_BHV_HEAD(vp), &xfs_vnodeops);
if (bdp == NULL)
if (bdp == NULL) {
XFS_STATS_INC(xfsstats.xs_ig_dup);
goto inode_allocate;
}
ip = XFS_BHVTOI(bdp);
if (lock_flags != 0)
xfs_ilock(ip, lock_flags);
......@@ -720,6 +727,9 @@ xfs_iextract(
}
}
/* Deal with the deleted inodes list */
list_del_init(&ip->i_reclaim);
mp->m_ireclaims++;
XFS_MOUNT_IUNLOCK(mp);
}
......
......@@ -656,7 +656,9 @@ xfs_iformat_extents(
int nex;
int real_size;
int size;
#if ARCH_CONVERT != ARCH_NOCONVERT
int i;
#endif
ifp = XFS_IFORK_PTR(ip, whichfork);
nex = XFS_DFORK_NEXTENTS_ARCH(dip, whichfork, ARCH_CONVERT);
......@@ -976,6 +978,8 @@ xfs_iread(
XFS_IFORK_DSIZE(ip) / (uint)sizeof(xfs_bmbt_rec_t);
}
INIT_LIST_HEAD(&ip->i_reclaim);
/*
* The inode format changed when we moved the link count and
* made it 32 bits long. If this is an old format inode,
......@@ -2625,6 +2629,15 @@ xfs_iunpin(
ASSERT(atomic_read(&ip->i_pincount) > 0);
if (atomic_dec_and_test(&ip->i_pincount)) {
vnode_t *vp = XFS_ITOV_NULL(ip);
/* make sync come back and flush this inode */
if (vp) {
struct inode *inode = LINVFS_GET_IP(vp);
mark_inode_dirty_sync(inode);
}
wake_up(&ip->i_ipin_wait);
}
}
......@@ -3640,6 +3653,8 @@ xfs_ichgtime(xfs_inode_t *ip,
*/
SYNCHRONIZE();
ip->i_update_core = 1;
if (!(inode->i_state & I_LOCK))
mark_inode_dirty(inode);
}
#ifdef XFS_ILOCK_TRACE
......
......@@ -243,6 +243,7 @@ typedef struct xfs_inode {
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*/
struct xfs_dquot *i_udquot; /* user dquot */
struct xfs_dquot *i_gdquot; /* group dquot */
......@@ -477,7 +478,7 @@ void xfs_iunlock_map_shared(xfs_inode_t *, uint);
void xfs_ifunlock(xfs_inode_t *);
void xfs_ireclaim(xfs_inode_t *);
int xfs_finish_reclaim(xfs_inode_t *, int, int);
int xfs_finish_reclaim_all(struct xfs_mount *);
int xfs_finish_reclaim_all(struct xfs_mount *, int);
/*
* xfs_inode.c prototypes.
......
/*
* Copyright (c) 2000-2002 Silicon Graphics, Inc. All Rights Reserved.
* Copyright (c) 2000-2003 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
......@@ -413,19 +413,6 @@ xfs_log_release_iclog(xfs_mount_t *mp,
return 0;
}
/*
* Initialize log manager data. This routine is intended to be called when
* a system boots up. It is not a per filesystem initialization.
*
* As you can see, we currently do nothing.
*/
int
xfs_log_init(void)
{
return( 0 );
}
/*
* 1. Reserve an amount of on-disk log space and return a ticket corresponding
* to the reservation.
......@@ -497,8 +484,6 @@ xfs_log_mount(xfs_mount_t *mp,
xfs_daddr_t blk_offset,
int num_bblks)
{
xlog_t *log;
if (!(mp->m_flags & XFS_MOUNT_NORECOVERY))
cmn_err(CE_NOTE, "XFS mounting filesystem %s", mp->m_fsname);
else {
......@@ -508,7 +493,7 @@ xfs_log_mount(xfs_mount_t *mp,
ASSERT(XFS_MTOVFS(mp)->vfs_flag & VFS_RDONLY);
}
mp->m_log = log = xlog_alloc_log(mp, log_dev, blk_offset, num_bblks);
mp->m_log = xlog_alloc_log(mp, log_dev, blk_offset, num_bblks);
#if defined(DEBUG) || defined(XLOG_NOLOG)
if (! xlog_debug) {
......@@ -528,19 +513,19 @@ xfs_log_mount(xfs_mount_t *mp,
if (readonly)
vfsp->vfs_flag &= ~VFS_RDONLY;
error = xlog_recover(log, readonly);
error = xlog_recover(mp->m_log, readonly);
if (readonly)
vfsp->vfs_flag |= VFS_RDONLY;
if (error) {
cmn_err(CE_WARN, "XFS: log mount/recovery failed");
xlog_unalloc_log(log);
xlog_unalloc_log(mp->m_log);
return error;
}
}
/* Normal transactions can now occur */
log->l_flags &= ~XLOG_ACTIVE_RECOVERY;
mp->m_log->l_flags &= ~XLOG_ACTIVE_RECOVERY;
/* End mounting message in xfs_log_mount_finish */
return 0;
......@@ -1191,14 +1176,13 @@ xlog_alloc_log(xfs_mount_t *mp,
int i;
int iclogsize;
log = (void *)kmem_zalloc(sizeof(xlog_t), KM_SLEEP);
log = (xlog_t *)kmem_zalloc(sizeof(xlog_t), KM_SLEEP);
log->l_mp = mp;
log->l_dev = log_dev;
log->l_logsize = BBTOB(num_bblks);
log->l_logBBstart = blk_offset;
log->l_logBBsize = num_bblks;
log->l_roundoff = 0;
log->l_covered_state = XLOG_STATE_COVER_IDLE;
log->l_flags |= XLOG_ACTIVE_RECOVERY;
......@@ -1207,12 +1191,24 @@ xlog_alloc_log(xfs_mount_t *mp,
/* log->l_tail_lsn = 0x100000000LL; cycle = 1; current block = 0 */
log->l_last_sync_lsn = log->l_tail_lsn;
log->l_curr_cycle = 1; /* 0 is bad since this is initial value */
log->l_curr_block = 0; /* filled in by xlog_recover */
log->l_grant_reserve_bytes = 0;
log->l_grant_reserve_cycle = 1;
log->l_grant_write_bytes = 0;
log->l_grant_write_cycle = 1;
log->l_quotaoffs_flag = 0; /* XFS_LI_QUOTAOFF logitems */
if (XFS_SB_VERSION_HASLOGV2(&mp->m_sb)) {
if (mp->m_sb.sb_logsunit <= 1) {
log->l_stripemask = 1;
} else {
log->l_stripemask = 1 <<
xfs_highbit32(mp->m_sb.sb_logsunit >> BBSHIFT);
}
}
if (XFS_SB_VERSION_HASSECTOR(&mp->m_sb)) {
log->l_sectbb_log = mp->m_sb.sb_logsectlog - BBSHIFT;
ASSERT(log->l_sectbb_log <= mp->m_sectbb_log);
ASSERT(XFS_SB_VERSION_HASLOGV2(&mp->m_sb));
ASSERT(mp->m_sb.sb_logsectlog >= BBSHIFT);
}
log->l_sectbb_mask = (1 << log->l_sectbb_log) - 1;
xlog_get_iclog_buffer_size(mp, log);
......@@ -2811,10 +2807,9 @@ xlog_state_switch_iclogs(xlog_t *log,
/* Round up to next log-sunit */
if (XFS_SB_VERSION_HASLOGV2(&log->l_mp->m_sb)) {
if (log->l_curr_block & (log->l_mp->m_lstripemask - 1)) {
roundup = log->l_mp->m_lstripemask -
(log->l_curr_block &
(log->l_mp->m_lstripemask - 1));
if (log->l_curr_block & (log->l_stripemask - 1)) {
roundup = log->l_stripemask -
(log->l_curr_block & (log->l_stripemask - 1));
} else {
roundup = 0;
}
......@@ -3293,15 +3288,17 @@ xlog_verify_disk_cycle_no(xlog_t *log,
{
xfs_buf_t *bp;
uint cycle_no;
xfs_caddr_t ptr;
xfs_daddr_t i;
if (BLOCK_LSN(iclog->ic_header.h_lsn, ARCH_CONVERT) < 10) {
cycle_no = CYCLE_LSN(iclog->ic_header.h_lsn, ARCH_CONVERT);
bp = xlog_get_bp(1, log->l_mp);
bp = xlog_get_bp(log, 1);
ASSERT(bp);
for (i = 0; i < BLOCK_LSN(iclog->ic_header.h_lsn, ARCH_CONVERT); i++) {
xlog_bread(log, i, 1, bp);
if (GET_CYCLE(XFS_BUF_PTR(bp), ARCH_CONVERT) != cycle_no)
ptr = xlog_align(log, i, 1, bp);
if (GET_CYCLE(ptr, ARCH_CONVERT) != cycle_no)
xlog_warn("XFS: xlog_verify_disk_cycle_no: bad cycle no");
}
xlog_put_bp(bp);
......
/*
* Copyright (c) 2000-2002 Silicon Graphics, Inc. All Rights Reserved.
* Copyright (c) 2000-2003 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
......@@ -153,7 +153,6 @@ xfs_lsn_t xfs_log_done(struct xfs_mount *mp,
int xfs_log_force(struct xfs_mount *mp,
xfs_lsn_t lsn,
uint flags);
int xfs_log_init(void);
int xfs_log_mount(struct xfs_mount *mp,
dev_t log_dev,
xfs_daddr_t start_block,
......
/*
* Copyright (c) 2000-2002 Silicon Graphics, Inc. All Rights Reserved.
* Copyright (c) 2000-2003 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
......@@ -73,6 +73,9 @@ int xlog_btolrbb(int b);
#define XLOG_HEADER_SIZE 512
#define XLOG_REC_SHIFT(log) \
BTOBB(1 << (XFS_SB_VERSION_HASLOGV2(&log->l_mp->m_sb) ? \
XLOG_MAX_RECORD_BSHIFT : XLOG_BIG_RECORD_BSHIFT))
#define XLOG_TOTAL_REC_SHIFT(log) \
BTOBB(XLOG_MAX_ICLOGS << (XFS_SB_VERSION_HASLOGV2(&log->l_mp->m_sb) ? \
XLOG_MAX_RECORD_BSHIFT : XLOG_BIG_RECORD_BSHIFT))
......@@ -202,9 +205,9 @@ void xlog_grant_add_space(struct log *log, int bytes, int type);
#define LOG_LOCK(log) mutex_spinlock(&(log)->l_icloglock)
#define LOG_UNLOCK(log, s) mutex_spinunlock(&(log)->l_icloglock, s)
#define xlog_panic(s) {cmn_err(CE_PANIC, s); }
#define xlog_exit(s) {cmn_err(CE_PANIC, s); }
#define xlog_warn(s) {cmn_err(CE_WARN, s); }
#define xlog_panic(args...) cmn_err(CE_PANIC, ## args)
#define xlog_exit(args...) cmn_err(CE_PANIC, ## args)
#define xlog_warn(args...) cmn_err(CE_WARN, ## args)
/*
* In core log state
......@@ -403,6 +406,7 @@ typedef struct xlog_rec_ext_header {
uint xh_cycle; /* write cycle of log : 4 */
uint xh_cycle_data[XLOG_HEADER_CYCLE_SIZE / BBSIZE]; /* : 256 */
} xlog_rec_ext_header_t;
#ifdef __KERNEL__
/*
* - A log record header is 512 bytes. There is plenty of room to grow the
......@@ -441,12 +445,10 @@ typedef struct xlog_iclog_fields {
char *ic_datap; /* pointer to iclog data */
} xlog_iclog_fields_t;
typedef struct xlog_in_core2 {
union {
typedef union xlog_in_core2 {
xlog_rec_header_t hic_header;
xlog_rec_ext_header_t hic_xheader;
char hic_sector[XLOG_HEADER_SIZE];
} ic_h;
} xlog_in_core_2_t;
typedef struct xlog_in_core {
......@@ -473,7 +475,7 @@ typedef struct xlog_in_core {
#define ic_bwritecnt hic_fields.ic_bwritecnt
#define ic_state hic_fields.ic_state
#define ic_datap hic_fields.ic_datap
#define ic_header hic_data->ic_h.hic_header
#define ic_header hic_data->hic_header
/*
* The reservation head lsn is not made up of a cycle number and block number.
......@@ -530,8 +532,11 @@ typedef struct log {
uint l_flags;
uint l_quotaoffs_flag;/* XFS_DQ_*, if QUOTAOFFs found */
struct xfs_buf_cancel **l_buf_cancel_table;
int l_stripemask; /* log stripe mask */
int l_iclog_hsize; /* size of iclog header */
int l_iclog_heads; /* number of iclog header sectors */
uint l_sectbb_log; /* log2 of sector size in bbs */
uint l_sectbb_mask; /* sector size in bbs alignment mask */
} xlog_t;
......@@ -546,11 +551,13 @@ extern int xlog_print_find_oldest(xlog_t *log, xfs_daddr_t *last_blk);
extern int xlog_recover(xlog_t *log, int readonly);
extern int xlog_recover_finish(xlog_t *log, int mfsi_flags);
extern void xlog_pack_data(xlog_t *log, xlog_in_core_t *iclog);
extern struct xfs_buf *xlog_get_bp(int,xfs_mount_t *);
extern void xlog_put_bp(struct xfs_buf *);
extern int xlog_bread(xlog_t *, xfs_daddr_t blkno, int bblks, struct xfs_buf *bp);
extern void xlog_recover_process_iunlinks(xlog_t *log);
extern struct xfs_buf *xlog_get_bp(xlog_t *, int);
extern void xlog_put_bp(struct xfs_buf *);
extern int xlog_bread(xlog_t *, xfs_daddr_t, int, struct xfs_buf *);
extern xfs_caddr_t xlog_align(xlog_t *, xfs_daddr_t, int, struct xfs_buf *);
#define XLOG_TRACE_GRAB_FLUSH 1
#define XLOG_TRACE_REL_FLUSH 2
#define XLOG_TRACE_SLEEP_FLUSH 3
......
This diff is collapsed.
......@@ -467,7 +467,11 @@ xfs_readsb(xfs_mount_t *mp)
bp = xfs_buf_read_flags(mp->m_ddev_targp, XFS_SB_DADDR,
BTOBB(sector_size), extra_flags);
ASSERT(bp);
if (!bp || XFS_BUF_ISERROR(bp)) {
cmn_err(CE_WARN, "XFS: SB read failed");
error = bp ? XFS_BUF_GETERROR(bp) : ENOMEM;
goto fail;
}
ASSERT(XFS_BUF_ISBUSY(bp));
ASSERT(XFS_BUF_VALUSEMA(bp) <= 0);
......@@ -482,9 +486,7 @@ xfs_readsb(xfs_mount_t *mp)
error = xfs_mount_validate_sb(mp, &(mp->m_sb));
if (error) {
cmn_err(CE_WARN, "XFS: SB validate failed");
XFS_BUF_UNMANAGE(bp);
xfs_buf_relse(bp);
return error;
goto fail;
}
/*
......@@ -494,9 +496,8 @@ xfs_readsb(xfs_mount_t *mp)
cmn_err(CE_WARN,
"XFS: device supports only %u byte sectors (not %u)",
sector_size, mp->m_sb.sb_sectsize);
XFS_BUF_UNMANAGE(bp);
xfs_buf_relse(bp);
return XFS_ERROR(ENOSYS);
error = ENOSYS;
goto fail;
}
/*
......@@ -509,7 +510,11 @@ xfs_readsb(xfs_mount_t *mp)
sector_size = mp->m_sb.sb_sectsize;
bp = xfs_buf_read_flags(mp->m_ddev_targp, XFS_SB_DADDR,
BTOBB(sector_size), extra_flags);
ASSERT(bp);
if (!bp || XFS_BUF_ISERROR(bp)) {
cmn_err(CE_WARN, "XFS: SB re-read failed");
error = bp ? XFS_BUF_GETERROR(bp) : ENOMEM;
goto fail;
}
ASSERT(XFS_BUF_ISBUSY(bp));
ASSERT(XFS_BUF_VALUSEMA(bp) <= 0);
}
......@@ -518,6 +523,13 @@ xfs_readsb(xfs_mount_t *mp)
xfs_buf_relse(bp);
ASSERT(XFS_BUF_VALUSEMA(bp) > 0);
return 0;
fail:
if (bp) {
XFS_BUF_UNMANAGE(bp);
xfs_buf_relse(bp);
}
return error;
}
......@@ -546,16 +558,7 @@ xfs_mount_common(xfs_mount_t *mp, xfs_sb_t *sbp)
mp->m_blockmask = sbp->sb_blocksize - 1;
mp->m_blockwsize = sbp->sb_blocksize >> XFS_WORDLOG;
mp->m_blockwmask = mp->m_blockwsize - 1;
if (XFS_SB_VERSION_HASLOGV2(sbp)) {
if (sbp->sb_logsunit <= 1) {
mp->m_lstripemask = 1;
} else {
mp->m_lstripemask =
1 << xfs_highbit32(sbp->sb_logsunit >> BBSHIFT);
}
}
INIT_LIST_HEAD(&mp->m_del_inodes);
/*
* Setup for attributes, in case they get created.
......@@ -601,7 +604,6 @@ xfs_mount_common(xfs_mount_t *mp, xfs_sb_t *sbp)
sbp->sb_inopblock);
mp->m_ialloc_blks = mp->m_ialloc_inos >> sbp->sb_inopblog;
}
/*
* xfs_mountfs
*
......
......@@ -68,6 +68,7 @@ typedef struct xfs_trans_reservations {
((xfs_agblock_t)(XFS_BB_TO_FSBT(mp, d) % (mp)->m_sb.sb_agblocks))
#else
struct cred;
struct log;
struct vfs;
struct vnode;
struct xfs_mount_args;
......@@ -296,13 +297,14 @@ typedef struct xfs_mount {
int 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 */
uint m_ireclaims; /* count of calls to reclaim*/
uint m_readio_log; /* min read size log bytes */
uint m_readio_blocks; /* min read size blocks */
uint m_writeio_log; /* min write size log bytes */
uint m_writeio_blocks; /* min write size blocks */
void *m_log; /* log specific stuff */
struct log *m_log; /* log specific stuff */
int m_logbufs; /* number of log buffers */
int m_logbsize; /* size of each log buffer */
uint m_rsumlevels; /* rt summary levels */
......@@ -357,7 +359,6 @@ typedef struct xfs_mount {
#endif
int m_dalign; /* stripe unit */
int m_swidth; /* stripe width */
int m_lstripemask; /* log stripe mask */
int m_sinoalign; /* stripe unit inode alignmnt */
int m_attr_magicpct;/* 37% of the blocksize */
int m_dir_magicpct; /* 37% of the dir blocksize */
......
......@@ -620,7 +620,7 @@ xfs_mntupdate(
if (*flags & MS_RDONLY) {
pagebuf_delwri_flush(mp->m_ddev_targp, 0, NULL);
xfs_finish_reclaim_all(mp);
xfs_finish_reclaim_all(mp, 0);
do {
VFS_SYNC(vfsp, SYNC_ATTR|SYNC_WAIT, NULL, error);
......@@ -849,19 +849,14 @@ xfs_sync(
* xfs sync routine for internal use
*
* This routine supports all of the flags defined for the generic VFS_SYNC
* interface as explained above under xys_sync. In the interests of not
* interface as explained above under xfs_sync. In the interests of not
* changing interfaces within the 6.5 family, additional internallly-
* required functions are specified within a separate xflags parameter,
* only available by calling this routine.
*
* xflags:
* XFS_XSYNC_RELOC - Sync for relocation. Don't try to get behavior
* locks as this will cause you to hang. Not all
* combinations of flags are necessarily supported
* when this is specified.
*/
int
xfs_syncsub(
STATIC int
xfs_sync_inodes(
xfs_mount_t *mp,
int flags,
int xflags,
......@@ -877,12 +872,10 @@ xfs_syncsub(
uint64_t fflag;
uint lock_flags;
uint base_lock_flags;
uint log_flags;
boolean_t mount_locked;
boolean_t vnode_refed;
int preempt;
xfs_dinode_t *dip;
xfs_buf_log_item_t *bip;
xfs_iptr_t *ipointer;
#ifdef DEBUG
boolean_t ipointer_in = B_FALSE;
......@@ -961,16 +954,6 @@ xfs_syncsub(
base_lock_flags |= XFS_IOLOCK_SHARED;
}
/*
* Sync out the log. This ensures that the log is periodically
* flushed even if there is not enough activity to fill it up.
*/
if (flags & SYNC_WAIT) {
xfs_log_force(mp, (xfs_lsn_t)0, XFS_LOG_FORCE | XFS_LOG_SYNC);
} else {
xfs_log_force(mp, (xfs_lsn_t)0, XFS_LOG_FORCE);
}
XFS_MOUNT_ILOCK(mp);
ip = mp->m_inodes;
......@@ -1016,9 +999,6 @@ xfs_syncsub(
ip = ip->i_mnext;
continue;
}
if ((ip->i_update_core == 0) &&
((ip->i_itemp == NULL) ||
!(ip->i_itemp->ili_format.ilf_fields & XFS_ILOG_ALL))) {
if (xfs_ilock_nowait(ip, XFS_ILOCK_EXCL) == 0) {
ip = ip->i_mnext;
} else if ((xfs_ipincount(ip) == 0) &&
......@@ -1026,7 +1006,7 @@ xfs_syncsub(
IPOINTER_INSERT(ip, mp);
xfs_finish_reclaim(ip, 1,
XFS_IFLUSH_DELWRI_ELSE_SYNC);
XFS_IFLUSH_DELWRI_ELSE_ASYNC);
XFS_MOUNT_ILOCK(mp);
mount_locked = B_TRUE;
......@@ -1037,7 +1017,6 @@ xfs_syncsub(
}
continue;
}
}
if (XFS_FORCED_SHUTDOWN(mp) && !(flags & SYNC_CLOSE)) {
XFS_MOUNT_IUNLOCK(mp);
......@@ -1148,22 +1127,10 @@ xfs_syncsub(
xfs_iunlock(ip, XFS_ILOCK_SHARED);
if (XFS_FORCED_SHUTDOWN(mp)) {
if (xflags & XFS_XSYNC_RELOC) {
fs_tosspages(XFS_ITOBHV(ip), 0, -1,
FI_REMAPF);
}
else {
VOP_TOSS_PAGES(vp, 0, -1, FI_REMAPF);
}
} else {
if (xflags & XFS_XSYNC_RELOC) {
fs_flushinval_pages(XFS_ITOBHV(ip),
0, -1, FI_REMAPF);
}
else {
VOP_FLUSHINVAL_PAGES(vp, 0, -1, FI_REMAPF);
}
}
xfs_ilock(ip, XFS_ILOCK_SHARED);
......@@ -1418,16 +1385,55 @@ xfs_syncsub(
ASSERT(ipointer_in == B_FALSE);
kmem_free(ipointer, sizeof(xfs_iptr_t));
return XFS_ERROR(last_error);
}
/*
* xfs sync routine for internal use
*
* This routine supports all of the flags defined for the generic VFS_SYNC
* interface as explained above under xfs_sync. In the interests of not
* changing interfaces within the 6.5 family, additional internallly-
* required functions are specified within a separate xflags parameter,
* only available by calling this routine.
*
*/
int
xfs_syncsub(
xfs_mount_t *mp,
int flags,
int xflags,
int *bypassed)
{
int error = 0;
int last_error = 0;
uint log_flags = XFS_LOG_FORCE;
xfs_buf_t *bp;
xfs_buf_log_item_t *bip;
/*
* Flushing out dirty data above probably generated more
* log activity, so if this isn't vfs_sync() then flush
* the log again. If SYNC_WAIT is set then do it synchronously.
* Sync out the log. This ensures that the log is periodically
* flushed even if there is not enough activity to fill it up.
*/
if (!(flags & SYNC_BDFLUSH)) {
log_flags = XFS_LOG_FORCE;
if (flags & SYNC_WAIT) {
if (flags & SYNC_WAIT)
log_flags |= XFS_LOG_SYNC;
xfs_log_force(mp, (xfs_lsn_t)0, log_flags);
if (flags & (SYNC_ATTR|SYNC_DELWRI)) {
if (flags & SYNC_BDFLUSH)
xfs_finish_reclaim_all(mp, 1);
else
error = xfs_sync_inodes(mp, flags, xflags, bypassed);
}
/*
* Flushing out dirty data above probably generated more
* log activity, so if this isn't vfs_sync() then flush
* the log again.
*/
if (flags & SYNC_DELWRI) {
xfs_log_force(mp, (xfs_lsn_t)0, log_flags);
}
......@@ -1463,11 +1469,10 @@ xfs_syncsub(
* that point so it can become pinned in between
* there and here.
*/
if (XFS_BUF_ISPINNED(bp)) {
xfs_log_force(mp, (xfs_lsn_t)0,
XFS_LOG_FORCE);
}
XFS_BUF_BFLAGS(bp) |= fflag;
if (XFS_BUF_ISPINNED(bp))
xfs_log_force(mp, (xfs_lsn_t)0, XFS_LOG_FORCE);
if (!(flags & SYNC_WAIT))
XFS_BUF_BFLAGS(bp) |= XFS_B_ASYNC;
error = xfs_bwrite(mp, bp);
}
if (error) {
......@@ -1478,9 +1483,9 @@ xfs_syncsub(
/*
* Now check to see if the log needs a "dummy" transaction.
*/
if (xfs_log_need_covered(mp)) {
xfs_trans_t *tp;
xfs_inode_t *ip;
/*
* Put a dummy transaction in the log to tell
......@@ -1491,7 +1496,6 @@ xfs_syncsub(
XFS_ICHANGE_LOG_RES(mp),
0, 0, 0))) {
xfs_trans_cancel(tp, 0);
kmem_free(ipointer, sizeof(xfs_iptr_t));
return error;
}
......@@ -1503,6 +1507,7 @@ xfs_syncsub(
xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
error = xfs_trans_commit(tp, 0, NULL);
xfs_iunlock(ip, XFS_ILOCK_EXCL);
xfs_log_force(mp, (xfs_lsn_t)0, XFS_LOG_FORCE);
}
/*
......@@ -1516,7 +1521,6 @@ xfs_syncsub(
}
}
kmem_free(ipointer, sizeof(xfs_iptr_t));
return XFS_ERROR(last_error);
}
......
......@@ -658,7 +658,7 @@ xfs_setattr(
if (vap->va_size > ip->i_d.di_size) {
code = xfs_igrow_start(ip, vap->va_size, credp);
xfs_iunlock(ip, XFS_ILOCK_EXCL);
} else if (vap->va_size < ip->i_d.di_size) {
} else if (vap->va_size <= ip->i_d.di_size) {
xfs_iunlock(ip, XFS_ILOCK_EXCL);
xfs_itruncate_start(ip, XFS_ITRUNC_DEFINITE,
(xfs_fsize_t)vap->va_size);
......@@ -701,7 +701,7 @@ xfs_setattr(
if (vap->va_size > ip->i_d.di_size) {
xfs_igrow_finish(tp, ip, vap->va_size,
!(flags & ATTR_DMI));
} else if ((vap->va_size < ip->i_d.di_size) ||
} else if ((vap->va_size <= ip->i_d.di_size) ||
((vap->va_size == 0) && ip->i_d.di_nextents)) {
/*
* signal a sync transaction unless
......@@ -3786,27 +3786,30 @@ xfs_inode_flush(
flush_flags = XFS_IFLUSH_SYNC;
else
#endif
flush_flags = XFS_IFLUSH_DELWRI;
flush_flags = XFS_IFLUSH_DELWRI_ELSE_ASYNC;
xfs_ifunlock(ip);
xfs_iunlock(ip, XFS_ILOCK_SHARED);
error = xfs_itobp(mp, NULL, ip, &dip, &bp, 0);
if (error)
goto eagain;
return error;
xfs_buf_relse(bp);
if (xfs_ilock_nowait(ip, XFS_ILOCK_SHARED) == 0)
goto eagain;
return EAGAIN;
if (xfs_ipincount(ip) ||
!xfs_iflock_nowait(ip)) {
xfs_iunlock(ip, XFS_ILOCK_SHARED);
return EAGAIN;
}
if ((xfs_ipincount(ip) == 0) &&
xfs_iflock_nowait(ip))
error = xfs_iflush(ip, flush_flags);
} else {
error = EAGAIN;
}
xfs_iunlock(ip, XFS_ILOCK_SHARED);
} else {
eagain:
error = EAGAIN;
}
}
......@@ -3934,6 +3937,8 @@ xfs_reclaim(
/* Protect sync from us */
XFS_MOUNT_ILOCK(mp);
vn_bhv_remove(VN_BHV_HEAD(vp), XFS_ITOBHV(ip));
list_add_tail(&ip->i_reclaim, &mp->m_del_inodes);
XFS_MOUNT_IUNLOCK(mp);
}
return 0;
......@@ -4010,40 +4015,33 @@ xfs_finish_reclaim(
}
int
xfs_finish_reclaim_all(xfs_mount_t *mp)
xfs_finish_reclaim_all(xfs_mount_t *mp, int noblock)
{
int purged;
struct list_head *curr, *next;
xfs_inode_t *ip;
vnode_t *vp;
int done = 0;
while (!done) {
purged = 0;
XFS_MOUNT_ILOCK(mp);
ip = mp->m_inodes;
if (ip == NULL) {
break;
}
do {
/* Make sure we skip markers inserted by sync */
if (ip->i_mount == NULL) {
ip = ip->i_mnext;
list_for_each_safe(curr, next, &mp->m_del_inodes) {
ip = list_entry(curr, xfs_inode_t, i_reclaim);
if (noblock) {
if (xfs_ilock_nowait(ip, XFS_ILOCK_EXCL) == 0)
continue;
if (xfs_ipincount(ip) ||
!xfs_iflock_nowait(ip)) {
xfs_iunlock(ip, XFS_ILOCK_EXCL);
continue;
}
/*
* It's up to our caller to purge the root
* and quota vnodes later.
*/
vp = XFS_ITOV_NULL(ip);
if (!vp) {
}
XFS_MOUNT_IUNLOCK(mp);
xfs_finish_reclaim(ip, 0, XFS_IFLUSH_ASYNC);
xfs_finish_reclaim(ip, noblock,
XFS_IFLUSH_DELWRI_ELSE_ASYNC);
purged = 1;
break;
}
} while (ip != mp->m_inodes);
done = !purged;
}
......
......@@ -4269,8 +4269,10 @@ xfsidbg_xlog(xlog_t *log)
kdb_printf("iclog_bak: 0x%p iclog_size: 0x%x (%d) num iclogs: %d\n",
log->l_iclog_bak, log->l_iclog_size, log->l_iclog_size,
log->l_iclog_bufs);
kdb_printf("l_iclog_hsize %d l_iclog_heads %d\n",
log->l_iclog_hsize, log->l_iclog_heads);
kdb_printf("l_stripemask %d l_iclog_hsize %d l_iclog_heads %d\n",
log->l_stripemask, log->l_iclog_hsize, log->l_iclog_heads);
kdb_printf("l_sectbb_log %u l_sectbb_mask %u\n",
log->l_sectbb_log, log->l_sectbb_mask);
kdb_printf("&grant_lock: 0x%p resHeadQ: 0x%p wrHeadQ: 0x%p\n",
&log->l_grant_lock, log->l_reserve_headq, log->l_write_headq);
kdb_printf("GResCycle: %d GResBytes: %d GWrCycle: %d GWrBytes: %d\n",
......@@ -4712,7 +4714,6 @@ xfsidbg_xmount(xfs_mount_t *mp)
(xfs_dfiloff_t)mp->m_dirfreeblk);
kdb_printf("chsize %d chash 0x%p\n",
mp->m_chsize, mp->m_chash);
kdb_printf("m_lstripemask %d\n", mp->m_lstripemask);
kdb_printf("m_frozen %d m_active_trans %d\n",
mp->m_frozen, mp->m_active_trans.counter);
if (mp->m_fsname != NULL)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment