diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2008-12-30 20:48:25 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-12-30 20:48:25 -0500 |
commit | 6a94cb73064c952255336cc57731904174b2c58f (patch) | |
tree | d19cc835db0a21e01909a92772868e1ad96f99ff /fs/xfs/linux-2.6/xfs_aops.c | |
parent | f57fa1d6a6b3414e853d3d17e339ac48816e4406 (diff) | |
parent | 0a8c5395f90f06d128247844b2515c8bf3f2826b (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.c | 66 |
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]) | ||
51 | static wait_queue_head_t xfs_ioend_wq[NVSYNC]; | ||
52 | |||
53 | void __init | ||
54 | xfs_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 | |||
62 | void | ||
63 | xfs_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 | |||
71 | STATIC void | ||
72 | xfs_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 | |||
45 | STATIC void | 79 | STATIC void |
46 | xfs_count_page_state( | 80 | xfs_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 | ||
330 | STATIC_INLINE int | 368 | STATIC_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 | } |