diff options
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 | } |