diff options
author | Christoph Hellwig <hch@sgi.com> | 2005-09-04 18:23:35 -0400 |
---|---|---|
committer | Nathan Scott <nathans@sgi.com> | 2005-09-04 18:23:35 -0400 |
commit | c1a073bdff997216eac25254a2716faf640e4e8d (patch) | |
tree | 0121a8f6fe10e62bbd943defafe6a92c03e633b6 /fs | |
parent | f09738638d3bae6501e8e160c66233832d8c280f (diff) |
[XFS] Delay I/O completion for unwritten extents after conversion
SGI-PV: 936584
SGI-Modid: xfs-linux:xfs-kern:196886a
Signed-off-by: Christoph Hellwig <hch@sgi.com>
Signed-off-by: Nathan Scott <nathans@sgi.com>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/xfs/linux-2.6/xfs_aops.c | 27 | ||||
-rw-r--r-- | fs/xfs/linux-2.6/xfs_aops.h | 1 |
2 files changed, 26 insertions, 2 deletions
diff --git a/fs/xfs/linux-2.6/xfs_aops.c b/fs/xfs/linux-2.6/xfs_aops.c index 2add9a8a8df7..ea615e2f476d 100644 --- a/fs/xfs/linux-2.6/xfs_aops.c +++ b/fs/xfs/linux-2.6/xfs_aops.c | |||
@@ -136,10 +136,21 @@ xfs_end_bio_unwritten( | |||
136 | vnode_t *vp = ioend->io_vnode; | 136 | vnode_t *vp = ioend->io_vnode; |
137 | xfs_off_t offset = ioend->io_offset; | 137 | xfs_off_t offset = ioend->io_offset; |
138 | size_t size = ioend->io_size; | 138 | size_t size = ioend->io_size; |
139 | struct buffer_head *bh, *next; | ||
139 | int error; | 140 | int error; |
140 | 141 | ||
141 | if (ioend->io_uptodate) | 142 | if (ioend->io_uptodate) |
142 | VOP_BMAP(vp, offset, size, BMAPI_UNWRITTEN, NULL, NULL, error); | 143 | VOP_BMAP(vp, offset, size, BMAPI_UNWRITTEN, NULL, NULL, error); |
144 | |||
145 | /* ioend->io_buffer_head is only non-NULL for buffered I/O */ | ||
146 | for (bh = ioend->io_buffer_head; bh; bh = next) { | ||
147 | next = bh->b_private; | ||
148 | |||
149 | bh->b_end_io = NULL; | ||
150 | clear_buffer_unwritten(bh); | ||
151 | end_buffer_async_write(bh, ioend->io_uptodate); | ||
152 | } | ||
153 | |||
143 | xfs_destroy_ioend(ioend); | 154 | xfs_destroy_ioend(ioend); |
144 | } | 155 | } |
145 | 156 | ||
@@ -165,6 +176,7 @@ xfs_alloc_ioend( | |||
165 | atomic_set(&ioend->io_remaining, 1); | 176 | atomic_set(&ioend->io_remaining, 1); |
166 | ioend->io_uptodate = 1; /* cleared if any I/O fails */ | 177 | ioend->io_uptodate = 1; /* cleared if any I/O fails */ |
167 | ioend->io_vnode = LINVFS_GET_VP(inode); | 178 | ioend->io_vnode = LINVFS_GET_VP(inode); |
179 | ioend->io_buffer_head = NULL; | ||
168 | atomic_inc(&ioend->io_vnode->v_iocount); | 180 | atomic_inc(&ioend->io_vnode->v_iocount); |
169 | ioend->io_offset = 0; | 181 | ioend->io_offset = 0; |
170 | ioend->io_size = 0; | 182 | ioend->io_size = 0; |
@@ -180,15 +192,26 @@ linvfs_unwritten_done( | |||
180 | int uptodate) | 192 | int uptodate) |
181 | { | 193 | { |
182 | xfs_ioend_t *ioend = bh->b_private; | 194 | xfs_ioend_t *ioend = bh->b_private; |
195 | static spinlock_t unwritten_done_lock = SPIN_LOCK_UNLOCKED; | ||
196 | unsigned long flags; | ||
183 | 197 | ||
184 | ASSERT(buffer_unwritten(bh)); | 198 | ASSERT(buffer_unwritten(bh)); |
185 | bh->b_end_io = NULL; | 199 | bh->b_end_io = NULL; |
186 | clear_buffer_unwritten(bh); | 200 | |
187 | if (!uptodate) | 201 | if (!uptodate) |
188 | ioend->io_uptodate = 0; | 202 | ioend->io_uptodate = 0; |
189 | 203 | ||
204 | /* | ||
205 | * Deep magic here. We reuse b_private in the buffer_heads to build | ||
206 | * a chain for completing the I/O from user context after we've issued | ||
207 | * a transaction to convert the unwritten extent. | ||
208 | */ | ||
209 | spin_lock_irqsave(&unwritten_done_lock, flags); | ||
210 | bh->b_private = ioend->io_buffer_head; | ||
211 | ioend->io_buffer_head = bh; | ||
212 | spin_unlock_irqrestore(&unwritten_done_lock, flags); | ||
213 | |||
190 | xfs_finish_ioend(ioend); | 214 | xfs_finish_ioend(ioend); |
191 | end_buffer_async_write(bh, uptodate); | ||
192 | } | 215 | } |
193 | 216 | ||
194 | STATIC int | 217 | STATIC int |
diff --git a/fs/xfs/linux-2.6/xfs_aops.h b/fs/xfs/linux-2.6/xfs_aops.h index ee46307a7321..2fa62974a04d 100644 --- a/fs/xfs/linux-2.6/xfs_aops.h +++ b/fs/xfs/linux-2.6/xfs_aops.h | |||
@@ -41,6 +41,7 @@ typedef struct xfs_ioend { | |||
41 | unsigned int io_uptodate; /* I/O status register */ | 41 | unsigned int io_uptodate; /* I/O status register */ |
42 | atomic_t io_remaining; /* hold count */ | 42 | atomic_t io_remaining; /* hold count */ |
43 | struct vnode *io_vnode; /* file being written to */ | 43 | struct vnode *io_vnode; /* file being written to */ |
44 | struct buffer_head *io_buffer_head;/* buffer linked list head */ | ||
44 | size_t io_size; /* size of the extent */ | 45 | size_t io_size; /* size of the extent */ |
45 | xfs_off_t io_offset; /* offset in the file */ | 46 | xfs_off_t io_offset; /* offset in the file */ |
46 | struct work_struct io_work; /* xfsdatad work queue */ | 47 | struct work_struct io_work; /* xfsdatad work queue */ |