aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs/linux-2.6/xfs_aops.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2008-12-30 20:48:25 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2008-12-30 20:48:25 -0500
commit6a94cb73064c952255336cc57731904174b2c58f (patch)
treed19cc835db0a21e01909a92772868e1ad96f99ff /fs/xfs/linux-2.6/xfs_aops.c
parentf57fa1d6a6b3414e853d3d17e339ac48816e4406 (diff)
parent0a8c5395f90f06d128247844b2515c8bf3f2826b (diff)
Merge branch 'for-linus' of git://oss.sgi.com/xfs/xfs
* 'for-linus' of git://oss.sgi.com/xfs/xfs: (184 commits) [XFS] Fix race in xfs_write() between direct and buffered I/O with DMAPI [XFS] handle unaligned data in xfs_bmbt_disk_get_all [XFS] avoid memory allocations in xfs_fs_vcmn_err [XFS] Fix speculative allocation beyond eof [XFS] Remove XFS_BUF_SHUT() and friends [XFS] Use the incore inode size in xfs_file_readdir() [XFS] set b_error from bio error in xfs_buf_bio_end_io [XFS] use inode_change_ok for setattr permission checking [XFS] add a FMODE flag to make XFS invisible I/O less hacky [XFS] resync headers with libxfs [XFS] simplify projid check in xfs_rename [XFS] replace b_fspriv with b_mount [XFS] Remove unused tracing code [XFS] Remove unnecessary assertion [XFS] Remove unused variable in ktrace_free() [XFS] Check return value of xfs_buf_get_noaddr() [XFS] Fix hang after disallowed rename across directory quota domains [XFS] Fix compile with CONFIG_COMPAT enabled move inode tracing out of xfs_vnode. move vn_iowait / vn_iowake into xfs_aops.c ...
Diffstat (limited to 'fs/xfs/linux-2.6/xfs_aops.c')
-rw-r--r--fs/xfs/linux-2.6/xfs_aops.c66
1 files changed, 52 insertions, 14 deletions
diff --git a/fs/xfs/linux-2.6/xfs_aops.c b/fs/xfs/linux-2.6/xfs_aops.c
index a44d68eb50b5..de3a198f771e 100644
--- a/fs/xfs/linux-2.6/xfs_aops.c
+++ b/fs/xfs/linux-2.6/xfs_aops.c
@@ -42,6 +42,40 @@
42#include <linux/pagevec.h> 42#include <linux/pagevec.h>
43#include <linux/writeback.h> 43#include <linux/writeback.h>
44 44
45
46/*
47 * Prime number of hash buckets since address is used as the key.
48 */
49#define NVSYNC 37
50#define to_ioend_wq(v) (&xfs_ioend_wq[((unsigned long)v) % NVSYNC])
51static wait_queue_head_t xfs_ioend_wq[NVSYNC];
52
53void __init
54xfs_ioend_init(void)
55{
56 int i;
57
58 for (i = 0; i < NVSYNC; i++)
59 init_waitqueue_head(&xfs_ioend_wq[i]);
60}
61
62void
63xfs_ioend_wait(
64 xfs_inode_t *ip)
65{
66 wait_queue_head_t *wq = to_ioend_wq(ip);
67
68 wait_event(*wq, (atomic_read(&ip->i_iocount) == 0));
69}
70
71STATIC void
72xfs_ioend_wake(
73 xfs_inode_t *ip)
74{
75 if (atomic_dec_and_test(&ip->i_iocount))
76 wake_up(to_ioend_wq(ip));
77}
78
45STATIC void 79STATIC void
46xfs_count_page_state( 80xfs_count_page_state(
47 struct page *page, 81 struct page *page,
@@ -146,16 +180,25 @@ xfs_destroy_ioend(
146 xfs_ioend_t *ioend) 180 xfs_ioend_t *ioend)
147{ 181{
148 struct buffer_head *bh, *next; 182 struct buffer_head *bh, *next;
183 struct xfs_inode *ip = XFS_I(ioend->io_inode);
149 184
150 for (bh = ioend->io_buffer_head; bh; bh = next) { 185 for (bh = ioend->io_buffer_head; bh; bh = next) {
151 next = bh->b_private; 186 next = bh->b_private;
152 bh->b_end_io(bh, !ioend->io_error); 187 bh->b_end_io(bh, !ioend->io_error);
153 } 188 }
154 if (unlikely(ioend->io_error)) { 189
155 vn_ioerror(XFS_I(ioend->io_inode), ioend->io_error, 190 /*
156 __FILE__,__LINE__); 191 * Volume managers supporting multiple paths can send back ENODEV
192 * when the final path disappears. In this case continuing to fill
193 * the page cache with dirty data which cannot be written out is
194 * evil, so prevent that.
195 */
196 if (unlikely(ioend->io_error == -ENODEV)) {
197 xfs_do_force_shutdown(ip->i_mount, SHUTDOWN_DEVICE_REQ,
198 __FILE__, __LINE__);
157 } 199 }
158 vn_iowake(XFS_I(ioend->io_inode)); 200
201 xfs_ioend_wake(ip);
159 mempool_free(ioend, xfs_ioend_pool); 202 mempool_free(ioend, xfs_ioend_pool);
160} 203}
161 204
@@ -191,7 +234,7 @@ xfs_setfilesize(
191 ip->i_d.di_size = isize; 234 ip->i_d.di_size = isize;
192 ip->i_update_core = 1; 235 ip->i_update_core = 1;
193 ip->i_update_size = 1; 236 ip->i_update_size = 1;
194 mark_inode_dirty_sync(ioend->io_inode); 237 xfs_mark_inode_dirty_sync(ip);
195 } 238 }
196 239
197 xfs_iunlock(ip, XFS_ILOCK_EXCL); 240 xfs_iunlock(ip, XFS_ILOCK_EXCL);
@@ -317,14 +360,9 @@ xfs_map_blocks(
317 xfs_iomap_t *mapp, 360 xfs_iomap_t *mapp,
318 int flags) 361 int flags)
319{ 362{
320 xfs_inode_t *ip = XFS_I(inode); 363 int nmaps = 1;
321 int error, nmaps = 1; 364
322 365 return -xfs_iomap(XFS_I(inode), offset, count, flags, mapp, &nmaps);
323 error = xfs_iomap(ip, offset, count,
324 flags, mapp, &nmaps);
325 if (!error && (flags & (BMAPI_WRITE|BMAPI_ALLOCATE)))
326 xfs_iflags_set(ip, XFS_IMODIFIED);
327 return -error;
328} 366}
329 367
330STATIC_INLINE int 368STATIC_INLINE int
@@ -512,7 +550,7 @@ xfs_cancel_ioend(
512 unlock_buffer(bh); 550 unlock_buffer(bh);
513 } while ((bh = next_bh) != NULL); 551 } while ((bh = next_bh) != NULL);
514 552
515 vn_iowake(XFS_I(ioend->io_inode)); 553 xfs_ioend_wake(XFS_I(ioend->io_inode));
516 mempool_free(ioend, xfs_ioend_pool); 554 mempool_free(ioend, xfs_ioend_pool);
517 } while ((ioend = next) != NULL); 555 } while ((ioend = next) != NULL);
518} 556}