aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@sgi.com>2005-09-04 18:23:35 -0400
committerNathan Scott <nathans@sgi.com>2005-09-04 18:23:35 -0400
commitc1a073bdff997216eac25254a2716faf640e4e8d (patch)
tree0121a8f6fe10e62bbd943defafe6a92c03e633b6 /fs
parentf09738638d3bae6501e8e160c66233832d8c280f (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.c27
-rw-r--r--fs/xfs/linux-2.6/xfs_aops.h1
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
194STATIC int 217STATIC 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 */