diff options
Diffstat (limited to 'fs/xfs/linux-2.6')
-rw-r--r-- | fs/xfs/linux-2.6/xfs_aops.c | 80 | ||||
-rw-r--r-- | fs/xfs/linux-2.6/xfs_buf.c | 11 | ||||
-rw-r--r-- | fs/xfs/linux-2.6/xfs_file.c | 50 | ||||
-rw-r--r-- | fs/xfs/linux-2.6/xfs_ioctl32.c | 29 | ||||
-rw-r--r-- | fs/xfs/linux-2.6/xfs_ioctl32.h | 6 | ||||
-rw-r--r-- | fs/xfs/linux-2.6/xfs_lrw.c | 3 | ||||
-rw-r--r-- | fs/xfs/linux-2.6/xfs_super.c | 3 | ||||
-rw-r--r-- | fs/xfs/linux-2.6/xfs_vnode.c | 5 | ||||
-rw-r--r-- | fs/xfs/linux-2.6/xfs_vnode.h | 10 |
9 files changed, 134 insertions, 63 deletions
diff --git a/fs/xfs/linux-2.6/xfs_aops.c b/fs/xfs/linux-2.6/xfs_aops.c index 76a84758073..93ce257cd14 100644 --- a/fs/xfs/linux-2.6/xfs_aops.c +++ b/fs/xfs/linux-2.6/xfs_aops.c @@ -558,7 +558,8 @@ xfs_submit_page( int i; BUG_ON(PageWriteback(page)); - set_page_writeback(page); + if (bh_count) + set_page_writeback(page); if (clear_dirty) clear_page_dirty(page); unlock_page(page); @@ -578,9 +579,6 @@ xfs_submit_page( if (probed_page && clear_dirty) wbc->nr_to_write--; /* Wrote an "extra" page */ - } else { - end_page_writeback(page); - wbc->pages_skipped++; /* We didn't write this page */ } } @@ -602,21 +600,26 @@ xfs_convert_page( { struct buffer_head *bh_arr[MAX_BUF_PER_PAGE], *bh, *head; xfs_iomap_t *mp = iomapp, *tmp; - unsigned long end, offset; - pgoff_t end_index; - int i = 0, index = 0; + unsigned long offset, end_offset; + int index = 0; int bbits = inode->i_blkbits; + int len, page_dirty; - end_index = i_size_read(inode) >> PAGE_CACHE_SHIFT; - if (page->index < end_index) { - end = PAGE_CACHE_SIZE; - } else { - end = i_size_read(inode) & (PAGE_CACHE_SIZE-1); - } + end_offset = (i_size_read(inode) & (PAGE_CACHE_SIZE - 1)); + + /* + * page_dirty is initially a count of buffers on the page before + * EOF and is decrememted as we move each into a cleanable state. + */ + len = 1 << inode->i_blkbits; + end_offset = max(end_offset, PAGE_CACHE_SIZE); + end_offset = roundup(end_offset, len); + page_dirty = end_offset / len; + + offset = 0; bh = head = page_buffers(page); do { - offset = i << bbits; - if (offset >= end) + if (offset >= end_offset) break; if (!(PageUptodate(page) || buffer_uptodate(bh))) continue; @@ -625,6 +628,7 @@ xfs_convert_page( if (startio) { lock_buffer(bh); bh_arr[index++] = bh; + page_dirty--; } continue; } @@ -657,10 +661,11 @@ xfs_convert_page( unlock_buffer(bh); mark_buffer_dirty(bh); } - } while (i++, (bh = bh->b_this_page) != head); + page_dirty--; + } while (offset += len, (bh = bh->b_this_page) != head); - if (startio) { - xfs_submit_page(page, wbc, bh_arr, index, 1, index == i); + if (startio && index) { + xfs_submit_page(page, wbc, bh_arr, index, 1, !page_dirty); } else { unlock_page(page); } @@ -725,8 +730,11 @@ xfs_page_state_convert( __uint64_t end_offset; pgoff_t end_index, last_index, tlast; int len, err, i, cnt = 0, uptodate = 1; - int flags = startio ? 0 : BMAPI_TRYLOCK; - int page_dirty, delalloc = 0; + int flags; + int page_dirty; + + /* wait for other IO threads? */ + flags = (startio && wbc->sync_mode != WB_SYNC_NONE) ? 0 : BMAPI_TRYLOCK; /* Is this page beyond the end of the file? */ offset = i_size_read(inode); @@ -740,19 +748,22 @@ xfs_page_state_convert( } } - offset = (loff_t)page->index << PAGE_CACHE_SHIFT; end_offset = min_t(unsigned long long, - offset + PAGE_CACHE_SIZE, i_size_read(inode)); - - bh = head = page_buffers(page); - iomp = NULL; + (loff_t)(page->index + 1) << PAGE_CACHE_SHIFT, offset); + offset = (loff_t)page->index << PAGE_CACHE_SHIFT; /* - * page_dirty is initially a count of buffers on the page and - * is decrememted as we move each into a cleanable state. + * page_dirty is initially a count of buffers on the page before + * EOF and is decrememted as we move each into a cleanable state. */ - len = bh->b_size; - page_dirty = PAGE_CACHE_SIZE / len; + len = 1 << inode->i_blkbits; + p_offset = max(p_offset, PAGE_CACHE_SIZE); + p_offset = roundup(p_offset, len); + page_dirty = p_offset / len; + + iomp = NULL; + p_offset = 0; + bh = head = page_buffers(page); do { if (offset >= end_offset) @@ -804,7 +815,6 @@ xfs_page_state_convert( */ } else if (buffer_delay(bh)) { if (!iomp) { - delalloc = 1; err = xfs_map_blocks(inode, offset, len, &iomap, BMAPI_ALLOCATE | flags); if (err) { @@ -875,14 +885,14 @@ xfs_page_state_convert( if (uptodate && bh == head) SetPageUptodate(page); - if (startio) - xfs_submit_page(page, wbc, bh_arr, cnt, 0, 1); + if (startio) { + xfs_submit_page(page, wbc, bh_arr, cnt, 0, !page_dirty); + } if (iomp) { - tlast = (iomp->iomap_offset + iomp->iomap_bsize - 1) >> + offset = (iomp->iomap_offset + iomp->iomap_bsize - 1) >> PAGE_CACHE_SHIFT; - if (delalloc && (tlast > last_index)) - tlast = last_index; + tlast = min_t(pgoff_t, offset, last_index); xfs_cluster_write(inode, page->index + 1, iomp, wbc, startio, unmapped, tlast); } diff --git a/fs/xfs/linux-2.6/xfs_buf.c b/fs/xfs/linux-2.6/xfs_buf.c index 23e0eb67fc2..997963e5362 100644 --- a/fs/xfs/linux-2.6/xfs_buf.c +++ b/fs/xfs/linux-2.6/xfs_buf.c @@ -1746,13 +1746,15 @@ STATIC DECLARE_COMPLETION(pagebuf_daemon_done); STATIC struct task_struct *pagebuf_daemon_task; STATIC int pagebuf_daemon_active; STATIC int force_flush; - +STATIC int force_sleep; STATIC int pagebuf_daemon_wakeup( int priority, unsigned int mask) { + if (force_sleep) + return 0; force_flush = 1; barrier(); wake_up_process(pagebuf_daemon_task); @@ -1778,7 +1780,12 @@ pagebuf_daemon( INIT_LIST_HEAD(&tmp); do { - try_to_freeze(PF_FREEZE); + if (unlikely(current->flags & PF_FREEZE)) { + force_sleep = 1; + refrigerator(PF_FREEZE); + } else { + force_sleep = 0; + } set_current_state(TASK_INTERRUPTIBLE); schedule_timeout((xfs_buf_timer_centisecs * HZ) / 100); diff --git a/fs/xfs/linux-2.6/xfs_file.c b/fs/xfs/linux-2.6/xfs_file.c index 9f057a4a5b0..24fa3b101b9 100644 --- a/fs/xfs/linux-2.6/xfs_file.c +++ b/fs/xfs/linux-2.6/xfs_file.c @@ -515,10 +515,49 @@ open_exec_out: } #endif /* HAVE_FOP_OPEN_EXEC */ +/* + * Temporary workaround to the AIO direct IO write problem. + * This code can go and we can revert to do_sync_write once + * the writepage(s) rework is merged. + */ +STATIC ssize_t +linvfs_write( + struct file *filp, + const char __user *buf, + size_t len, + loff_t *ppos) +{ + struct kiocb kiocb; + ssize_t ret; + + init_sync_kiocb(&kiocb, filp); + kiocb.ki_pos = *ppos; + ret = __linvfs_write(&kiocb, buf, 0, len, kiocb.ki_pos); + *ppos = kiocb.ki_pos; + return ret; +} +STATIC ssize_t +linvfs_write_invis( + struct file *filp, + const char __user *buf, + size_t len, + loff_t *ppos) +{ + struct kiocb kiocb; + ssize_t ret; + + init_sync_kiocb(&kiocb, filp); + kiocb.ki_pos = *ppos; + ret = __linvfs_write(&kiocb, buf, IO_INVIS, len, kiocb.ki_pos); + *ppos = kiocb.ki_pos; + return ret; +} + + struct file_operations linvfs_file_operations = { .llseek = generic_file_llseek, .read = do_sync_read, - .write = do_sync_write, + .write = linvfs_write, .readv = linvfs_readv, .writev = linvfs_writev, .aio_read = linvfs_aio_read, @@ -526,7 +565,7 @@ struct file_operations linvfs_file_operations = { .sendfile = linvfs_sendfile, .unlocked_ioctl = linvfs_ioctl, #ifdef CONFIG_COMPAT - .compat_ioctl = xfs_compat_ioctl, + .compat_ioctl = linvfs_compat_ioctl, #endif .mmap = linvfs_file_mmap, .open = linvfs_open, @@ -540,7 +579,7 @@ struct file_operations linvfs_file_operations = { struct file_operations linvfs_invis_file_operations = { .llseek = generic_file_llseek, .read = do_sync_read, - .write = do_sync_write, + .write = linvfs_write_invis, .readv = linvfs_readv_invis, .writev = linvfs_writev_invis, .aio_read = linvfs_aio_read_invis, @@ -548,7 +587,7 @@ struct file_operations linvfs_invis_file_operations = { .sendfile = linvfs_sendfile, .unlocked_ioctl = linvfs_ioctl_invis, #ifdef CONFIG_COMPAT - .compat_ioctl = xfs_compat_invis_ioctl, + .compat_ioctl = linvfs_compat_invis_ioctl, #endif .mmap = linvfs_file_mmap, .open = linvfs_open, @@ -561,6 +600,9 @@ struct file_operations linvfs_dir_operations = { .read = generic_read_dir, .readdir = linvfs_readdir, .unlocked_ioctl = linvfs_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = linvfs_compat_ioctl, +#endif .fsync = linvfs_fsync, }; diff --git a/fs/xfs/linux-2.6/xfs_ioctl32.c b/fs/xfs/linux-2.6/xfs_ioctl32.c index 7a12c83184f..0f8f1384eb3 100644 --- a/fs/xfs/linux-2.6/xfs_ioctl32.c +++ b/fs/xfs/linux-2.6/xfs_ioctl32.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004 Silicon Graphics, Inc. All Rights Reserved. + * Copyright (c) 2004-2005 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 @@ -58,8 +58,9 @@ typedef struct xfs_fsop_bulkreq32 { __s32 ocount; /* output count pointer */ } xfs_fsop_bulkreq32_t; -static unsigned long -xfs_ioctl32_bulkstat(unsigned long arg) +STATIC unsigned long +xfs_ioctl32_bulkstat( + unsigned long arg) { xfs_fsop_bulkreq32_t __user *p32 = (void __user *)arg; xfs_fsop_bulkreq_t __user *p = compat_alloc_user_space(sizeof(*p)); @@ -78,11 +79,11 @@ xfs_ioctl32_bulkstat(unsigned long arg) } #endif -static long -__xfs_compat_ioctl(int mode, struct file *f, unsigned cmd, unsigned long arg) +STATIC long +__linvfs_compat_ioctl(int mode, struct file *f, unsigned cmd, unsigned long arg) { int error; - struct inode *inode = f->f_dentry->d_inode; + struct inode *inode = f->f_dentry->d_inode; vnode_t *vp = LINVFS_GET_VP(inode); switch (cmd) { @@ -152,12 +153,20 @@ __xfs_compat_ioctl(int mode, struct file *f, unsigned cmd, unsigned long arg) return error; } -long xfs_compat_ioctl(struct file *f, unsigned cmd, unsigned long arg) +long +linvfs_compat_ioctl( + struct file *f, + unsigned cmd, + unsigned long arg) { - return __xfs_compat_ioctl(0, f, cmd, arg); + return __linvfs_compat_ioctl(0, f, cmd, arg); } -long xfs_compat_invis_ioctl(struct file *f, unsigned cmd, unsigned long arg) +long +linvfs_compat_invis_ioctl( + struct file *f, + unsigned cmd, + unsigned long arg) { - return __xfs_compat_ioctl(IO_INVIS, f, cmd, arg); + return __linvfs_compat_ioctl(IO_INVIS, f, cmd, arg); } diff --git a/fs/xfs/linux-2.6/xfs_ioctl32.h b/fs/xfs/linux-2.6/xfs_ioctl32.h index 779f69a4811..c874793a1dc 100644 --- a/fs/xfs/linux-2.6/xfs_ioctl32.h +++ b/fs/xfs/linux-2.6/xfs_ioctl32.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004 Silicon Graphics, Inc. All Rights Reserved. + * Copyright (c) 2004-2005 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 @@ -30,5 +30,5 @@ * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/ */ -long xfs_compat_ioctl(struct file *f, unsigned cmd, unsigned long arg); -long xfs_compat_invis_ioctl(struct file *f, unsigned cmd, unsigned long arg); +long linvfs_compat_ioctl(struct file *f, unsigned cmd, unsigned long arg); +long linvfs_compat_invis_ioctl(struct file *f, unsigned cmd, unsigned long arg); diff --git a/fs/xfs/linux-2.6/xfs_lrw.c b/fs/xfs/linux-2.6/xfs_lrw.c index ff145fd0d1a..aa9daaea6c3 100644 --- a/fs/xfs/linux-2.6/xfs_lrw.c +++ b/fs/xfs/linux-2.6/xfs_lrw.c @@ -683,6 +683,9 @@ xfs_write( (xip->i_d.di_flags & XFS_DIFLAG_REALTIME) ? mp->m_rtdev_targp : mp->m_ddev_targp; + if (ioflags & IO_ISAIO) + return XFS_ERROR(-ENOSYS); + if ((pos & target->pbr_smask) || (count & target->pbr_smask)) return XFS_ERROR(-EINVAL); diff --git a/fs/xfs/linux-2.6/xfs_super.c b/fs/xfs/linux-2.6/xfs_super.c index 53dc658cafa..455e2b2fb96 100644 --- a/fs/xfs/linux-2.6/xfs_super.c +++ b/fs/xfs/linux-2.6/xfs_super.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2004 Silicon Graphics, Inc. All Rights Reserved. + * 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 version 2 of the GNU General Public License as @@ -66,7 +66,6 @@ #include "xfs_buf_item.h" #include "xfs_utils.h" #include "xfs_version.h" -#include "xfs_ioctl32.h" #include <linux/namei.h> #include <linux/init.h> diff --git a/fs/xfs/linux-2.6/xfs_vnode.c b/fs/xfs/linux-2.6/xfs_vnode.c index 849c61c74f3..a832d165f24 100644 --- a/fs/xfs/linux-2.6/xfs_vnode.c +++ b/fs/xfs/linux-2.6/xfs_vnode.c @@ -156,7 +156,6 @@ vn_initialize( #ifdef XFS_VNODE_TRACE vp->v_trace = ktrace_alloc(VNODE_TRACE_SIZE, KM_SLEEP); - printk("Allocated VNODE_TRACE at 0x%p\n", vp->v_trace); #endif /* XFS_VNODE_TRACE */ vn_trace_exit(vp, "vn_initialize", (inst_t *)__return_address); @@ -424,13 +423,13 @@ vn_remove( * Vnode tracing code. */ void -vn_trace_entry(vnode_t *vp, char *func, inst_t *ra) +vn_trace_entry(vnode_t *vp, const char *func, inst_t *ra) { KTRACE_ENTER(vp, VNODE_KTRACE_ENTRY, func, 0, ra); } void -vn_trace_exit(vnode_t *vp, char *func, inst_t *ra) +vn_trace_exit(vnode_t *vp, const char *func, inst_t *ra) { KTRACE_ENTER(vp, VNODE_KTRACE_EXIT, func, 0, ra); } diff --git a/fs/xfs/linux-2.6/xfs_vnode.h b/fs/xfs/linux-2.6/xfs_vnode.h index da76c1f1e11..00466c3194a 100644 --- a/fs/xfs/linux-2.6/xfs_vnode.h +++ b/fs/xfs/linux-2.6/xfs_vnode.h @@ -86,10 +86,11 @@ typedef struct vnode { vnumber_t v_number; /* in-core vnode number */ vn_bhv_head_t v_bh; /* behavior head */ spinlock_t v_lock; /* VN_LOCK/VN_UNLOCK */ - struct inode v_inode; /* Linux inode */ #ifdef XFS_VNODE_TRACE struct ktrace *v_trace; /* trace header structure */ #endif + struct inode v_inode; /* Linux inode */ + /* inode MUST be last */ } vnode_t; #define v_fbhv v_bh.bh_first /* first behavior */ @@ -409,7 +410,7 @@ typedef struct vattr { int va_mask; /* bit-mask of attributes present */ enum vtype va_type; /* vnode type (for create) */ mode_t va_mode; /* file access mode and type */ - nlink_t va_nlink; /* number of references to file */ + xfs_nlink_t va_nlink; /* number of references to file */ uid_t va_uid; /* owner user id */ gid_t va_gid; /* owner group id */ xfs_ino_t va_nodeid; /* file id */ @@ -625,6 +626,7 @@ static inline int VN_BAD(struct vnode *vp) #define ATTR_DMI 0x08 /* invocation from a DMI function */ #define ATTR_LAZY 0x80 /* set/get attributes lazily */ #define ATTR_NONBLOCK 0x100 /* return EAGAIN if operation would block */ +#define ATTR_NOLOCK 0x200 /* Don't grab any conflicting locks */ /* * Flags to VOP_FSYNC and VOP_RECLAIM. @@ -646,8 +648,8 @@ static inline int VN_BAD(struct vnode *vp) #define VNODE_KTRACE_REF 4 #define VNODE_KTRACE_RELE 5 -extern void vn_trace_entry(struct vnode *, char *, inst_t *); -extern void vn_trace_exit(struct vnode *, char *, inst_t *); +extern void vn_trace_entry(struct vnode *, const char *, inst_t *); +extern void vn_trace_exit(struct vnode *, const char *, inst_t *); extern void vn_trace_hold(struct vnode *, char *, int, inst_t *); extern void vn_trace_ref(struct vnode *, char *, int, inst_t *); extern void vn_trace_rele(struct vnode *, char *, int, inst_t *); |