diff options
Diffstat (limited to 'fs/xfs/xfs_iomap.c')
-rw-r--r-- | fs/xfs/xfs_iomap.c | 212 |
1 files changed, 108 insertions, 104 deletions
diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c index 72786e356d56..fde37f87d52f 100644 --- a/fs/xfs/xfs_iomap.c +++ b/fs/xfs/xfs_iomap.c | |||
@@ -53,12 +53,10 @@ | |||
53 | void | 53 | void |
54 | xfs_iomap_enter_trace( | 54 | xfs_iomap_enter_trace( |
55 | int tag, | 55 | int tag, |
56 | xfs_iocore_t *io, | 56 | xfs_inode_t *ip, |
57 | xfs_off_t offset, | 57 | xfs_off_t offset, |
58 | ssize_t count) | 58 | ssize_t count) |
59 | { | 59 | { |
60 | xfs_inode_t *ip = XFS_IO_INODE(io); | ||
61 | |||
62 | if (!ip->i_rwtrace) | 60 | if (!ip->i_rwtrace) |
63 | return; | 61 | return; |
64 | 62 | ||
@@ -70,8 +68,8 @@ xfs_iomap_enter_trace( | |||
70 | (void *)((unsigned long)((offset >> 32) & 0xffffffff)), | 68 | (void *)((unsigned long)((offset >> 32) & 0xffffffff)), |
71 | (void *)((unsigned long)(offset & 0xffffffff)), | 69 | (void *)((unsigned long)(offset & 0xffffffff)), |
72 | (void *)((unsigned long)count), | 70 | (void *)((unsigned long)count), |
73 | (void *)((unsigned long)((io->io_new_size >> 32) & 0xffffffff)), | 71 | (void *)((unsigned long)((ip->i_new_size >> 32) & 0xffffffff)), |
74 | (void *)((unsigned long)(io->io_new_size & 0xffffffff)), | 72 | (void *)((unsigned long)(ip->i_new_size & 0xffffffff)), |
75 | (void *)((unsigned long)current_pid()), | 73 | (void *)((unsigned long)current_pid()), |
76 | (void *)NULL, | 74 | (void *)NULL, |
77 | (void *)NULL, | 75 | (void *)NULL, |
@@ -84,15 +82,13 @@ xfs_iomap_enter_trace( | |||
84 | void | 82 | void |
85 | xfs_iomap_map_trace( | 83 | xfs_iomap_map_trace( |
86 | int tag, | 84 | int tag, |
87 | xfs_iocore_t *io, | 85 | xfs_inode_t *ip, |
88 | xfs_off_t offset, | 86 | xfs_off_t offset, |
89 | ssize_t count, | 87 | ssize_t count, |
90 | xfs_iomap_t *iomapp, | 88 | xfs_iomap_t *iomapp, |
91 | xfs_bmbt_irec_t *imapp, | 89 | xfs_bmbt_irec_t *imapp, |
92 | int flags) | 90 | int flags) |
93 | { | 91 | { |
94 | xfs_inode_t *ip = XFS_IO_INODE(io); | ||
95 | |||
96 | if (!ip->i_rwtrace) | 92 | if (!ip->i_rwtrace) |
97 | return; | 93 | return; |
98 | 94 | ||
@@ -126,7 +122,7 @@ xfs_iomap_map_trace( | |||
126 | 122 | ||
127 | STATIC int | 123 | STATIC int |
128 | xfs_imap_to_bmap( | 124 | xfs_imap_to_bmap( |
129 | xfs_iocore_t *io, | 125 | xfs_inode_t *ip, |
130 | xfs_off_t offset, | 126 | xfs_off_t offset, |
131 | xfs_bmbt_irec_t *imap, | 127 | xfs_bmbt_irec_t *imap, |
132 | xfs_iomap_t *iomapp, | 128 | xfs_iomap_t *iomapp, |
@@ -134,11 +130,10 @@ xfs_imap_to_bmap( | |||
134 | int iomaps, /* Number of iomap entries */ | 130 | int iomaps, /* Number of iomap entries */ |
135 | int flags) | 131 | int flags) |
136 | { | 132 | { |
137 | xfs_mount_t *mp; | 133 | xfs_mount_t *mp = ip->i_mount; |
138 | int pbm; | 134 | int pbm; |
139 | xfs_fsblock_t start_block; | 135 | xfs_fsblock_t start_block; |
140 | 136 | ||
141 | mp = io->io_mount; | ||
142 | 137 | ||
143 | for (pbm = 0; imaps && pbm < iomaps; imaps--, iomapp++, imap++, pbm++) { | 138 | for (pbm = 0; imaps && pbm < iomaps; imaps--, iomapp++, imap++, pbm++) { |
144 | iomapp->iomap_offset = XFS_FSB_TO_B(mp, imap->br_startoff); | 139 | iomapp->iomap_offset = XFS_FSB_TO_B(mp, imap->br_startoff); |
@@ -146,7 +141,7 @@ xfs_imap_to_bmap( | |||
146 | iomapp->iomap_bsize = XFS_FSB_TO_B(mp, imap->br_blockcount); | 141 | iomapp->iomap_bsize = XFS_FSB_TO_B(mp, imap->br_blockcount); |
147 | iomapp->iomap_flags = flags; | 142 | iomapp->iomap_flags = flags; |
148 | 143 | ||
149 | if (io->io_flags & XFS_IOCORE_RT) { | 144 | if (XFS_IS_REALTIME_INODE(ip)) { |
150 | iomapp->iomap_flags |= IOMAP_REALTIME; | 145 | iomapp->iomap_flags |= IOMAP_REALTIME; |
151 | iomapp->iomap_target = mp->m_rtdev_targp; | 146 | iomapp->iomap_target = mp->m_rtdev_targp; |
152 | } else { | 147 | } else { |
@@ -160,7 +155,7 @@ xfs_imap_to_bmap( | |||
160 | iomapp->iomap_bn = IOMAP_DADDR_NULL; | 155 | iomapp->iomap_bn = IOMAP_DADDR_NULL; |
161 | iomapp->iomap_flags |= IOMAP_DELAY; | 156 | iomapp->iomap_flags |= IOMAP_DELAY; |
162 | } else { | 157 | } else { |
163 | iomapp->iomap_bn = XFS_FSB_TO_DB_IO(io, start_block); | 158 | iomapp->iomap_bn = XFS_FSB_TO_DB(ip, start_block); |
164 | if (ISUNWRITTEN(imap)) | 159 | if (ISUNWRITTEN(imap)) |
165 | iomapp->iomap_flags |= IOMAP_UNWRITTEN; | 160 | iomapp->iomap_flags |= IOMAP_UNWRITTEN; |
166 | } | 161 | } |
@@ -172,14 +167,14 @@ xfs_imap_to_bmap( | |||
172 | 167 | ||
173 | int | 168 | int |
174 | xfs_iomap( | 169 | xfs_iomap( |
175 | xfs_iocore_t *io, | 170 | xfs_inode_t *ip, |
176 | xfs_off_t offset, | 171 | xfs_off_t offset, |
177 | ssize_t count, | 172 | ssize_t count, |
178 | int flags, | 173 | int flags, |
179 | xfs_iomap_t *iomapp, | 174 | xfs_iomap_t *iomapp, |
180 | int *niomaps) | 175 | int *niomaps) |
181 | { | 176 | { |
182 | xfs_mount_t *mp = io->io_mount; | 177 | xfs_mount_t *mp = ip->i_mount; |
183 | xfs_fileoff_t offset_fsb, end_fsb; | 178 | xfs_fileoff_t offset_fsb, end_fsb; |
184 | int error = 0; | 179 | int error = 0; |
185 | int lockmode = 0; | 180 | int lockmode = 0; |
@@ -188,45 +183,37 @@ xfs_iomap( | |||
188 | int bmapi_flags = 0; | 183 | int bmapi_flags = 0; |
189 | int iomap_flags = 0; | 184 | int iomap_flags = 0; |
190 | 185 | ||
186 | ASSERT((ip->i_d.di_mode & S_IFMT) == S_IFREG); | ||
187 | |||
191 | if (XFS_FORCED_SHUTDOWN(mp)) | 188 | if (XFS_FORCED_SHUTDOWN(mp)) |
192 | return XFS_ERROR(EIO); | 189 | return XFS_ERROR(EIO); |
193 | 190 | ||
194 | switch (flags & | 191 | switch (flags & (BMAPI_READ | BMAPI_WRITE | BMAPI_ALLOCATE)) { |
195 | (BMAPI_READ | BMAPI_WRITE | BMAPI_ALLOCATE | | ||
196 | BMAPI_UNWRITTEN | BMAPI_DEVICE)) { | ||
197 | case BMAPI_READ: | 192 | case BMAPI_READ: |
198 | xfs_iomap_enter_trace(XFS_IOMAP_READ_ENTER, io, offset, count); | 193 | xfs_iomap_enter_trace(XFS_IOMAP_READ_ENTER, ip, offset, count); |
199 | lockmode = XFS_LCK_MAP_SHARED(mp, io); | 194 | lockmode = xfs_ilock_map_shared(ip); |
200 | bmapi_flags = XFS_BMAPI_ENTIRE; | 195 | bmapi_flags = XFS_BMAPI_ENTIRE; |
201 | break; | 196 | break; |
202 | case BMAPI_WRITE: | 197 | case BMAPI_WRITE: |
203 | xfs_iomap_enter_trace(XFS_IOMAP_WRITE_ENTER, io, offset, count); | 198 | xfs_iomap_enter_trace(XFS_IOMAP_WRITE_ENTER, ip, offset, count); |
204 | lockmode = XFS_ILOCK_EXCL|XFS_EXTSIZE_WR; | 199 | lockmode = XFS_ILOCK_EXCL|XFS_EXTSIZE_WR; |
205 | if (flags & BMAPI_IGNSTATE) | 200 | if (flags & BMAPI_IGNSTATE) |
206 | bmapi_flags |= XFS_BMAPI_IGSTATE|XFS_BMAPI_ENTIRE; | 201 | bmapi_flags |= XFS_BMAPI_IGSTATE|XFS_BMAPI_ENTIRE; |
207 | XFS_ILOCK(mp, io, lockmode); | 202 | xfs_ilock(ip, lockmode); |
208 | break; | 203 | break; |
209 | case BMAPI_ALLOCATE: | 204 | case BMAPI_ALLOCATE: |
210 | xfs_iomap_enter_trace(XFS_IOMAP_ALLOC_ENTER, io, offset, count); | 205 | xfs_iomap_enter_trace(XFS_IOMAP_ALLOC_ENTER, ip, offset, count); |
211 | lockmode = XFS_ILOCK_SHARED|XFS_EXTSIZE_RD; | 206 | lockmode = XFS_ILOCK_SHARED|XFS_EXTSIZE_RD; |
212 | bmapi_flags = XFS_BMAPI_ENTIRE; | 207 | bmapi_flags = XFS_BMAPI_ENTIRE; |
208 | |||
213 | /* Attempt non-blocking lock */ | 209 | /* Attempt non-blocking lock */ |
214 | if (flags & BMAPI_TRYLOCK) { | 210 | if (flags & BMAPI_TRYLOCK) { |
215 | if (!XFS_ILOCK_NOWAIT(mp, io, lockmode)) | 211 | if (!xfs_ilock_nowait(ip, lockmode)) |
216 | return XFS_ERROR(EAGAIN); | 212 | return XFS_ERROR(EAGAIN); |
217 | } else { | 213 | } else { |
218 | XFS_ILOCK(mp, io, lockmode); | 214 | xfs_ilock(ip, lockmode); |
219 | } | 215 | } |
220 | break; | 216 | break; |
221 | case BMAPI_UNWRITTEN: | ||
222 | goto phase2; | ||
223 | case BMAPI_DEVICE: | ||
224 | lockmode = XFS_LCK_MAP_SHARED(mp, io); | ||
225 | iomapp->iomap_target = io->io_flags & XFS_IOCORE_RT ? | ||
226 | mp->m_rtdev_targp : mp->m_ddev_targp; | ||
227 | error = 0; | ||
228 | *niomaps = 1; | ||
229 | goto out; | ||
230 | default: | 217 | default: |
231 | BUG(); | 218 | BUG(); |
232 | } | 219 | } |
@@ -237,7 +224,7 @@ xfs_iomap( | |||
237 | end_fsb = XFS_B_TO_FSB(mp, (xfs_ufsize_t)offset + count); | 224 | end_fsb = XFS_B_TO_FSB(mp, (xfs_ufsize_t)offset + count); |
238 | offset_fsb = XFS_B_TO_FSBT(mp, offset); | 225 | offset_fsb = XFS_B_TO_FSBT(mp, offset); |
239 | 226 | ||
240 | error = XFS_BMAPI(mp, NULL, io, offset_fsb, | 227 | error = xfs_bmapi(NULL, ip, offset_fsb, |
241 | (xfs_filblks_t)(end_fsb - offset_fsb), | 228 | (xfs_filblks_t)(end_fsb - offset_fsb), |
242 | bmapi_flags, NULL, 0, &imap, | 229 | bmapi_flags, NULL, 0, &imap, |
243 | &nimaps, NULL, NULL); | 230 | &nimaps, NULL, NULL); |
@@ -245,54 +232,48 @@ xfs_iomap( | |||
245 | if (error) | 232 | if (error) |
246 | goto out; | 233 | goto out; |
247 | 234 | ||
248 | phase2: | 235 | switch (flags & (BMAPI_WRITE|BMAPI_ALLOCATE)) { |
249 | switch (flags & (BMAPI_WRITE|BMAPI_ALLOCATE|BMAPI_UNWRITTEN)) { | ||
250 | case BMAPI_WRITE: | 236 | case BMAPI_WRITE: |
251 | /* If we found an extent, return it */ | 237 | /* If we found an extent, return it */ |
252 | if (nimaps && | 238 | if (nimaps && |
253 | (imap.br_startblock != HOLESTARTBLOCK) && | 239 | (imap.br_startblock != HOLESTARTBLOCK) && |
254 | (imap.br_startblock != DELAYSTARTBLOCK)) { | 240 | (imap.br_startblock != DELAYSTARTBLOCK)) { |
255 | xfs_iomap_map_trace(XFS_IOMAP_WRITE_MAP, io, | 241 | xfs_iomap_map_trace(XFS_IOMAP_WRITE_MAP, ip, |
256 | offset, count, iomapp, &imap, flags); | 242 | offset, count, iomapp, &imap, flags); |
257 | break; | 243 | break; |
258 | } | 244 | } |
259 | 245 | ||
260 | if (flags & (BMAPI_DIRECT|BMAPI_MMAP)) { | 246 | if (flags & (BMAPI_DIRECT|BMAPI_MMAP)) { |
261 | error = XFS_IOMAP_WRITE_DIRECT(mp, io, offset, | 247 | error = xfs_iomap_write_direct(ip, offset, count, flags, |
262 | count, flags, &imap, &nimaps, nimaps); | 248 | &imap, &nimaps, nimaps); |
263 | } else { | 249 | } else { |
264 | error = XFS_IOMAP_WRITE_DELAY(mp, io, offset, count, | 250 | error = xfs_iomap_write_delay(ip, offset, count, flags, |
265 | flags, &imap, &nimaps); | 251 | &imap, &nimaps); |
266 | } | 252 | } |
267 | if (!error) { | 253 | if (!error) { |
268 | xfs_iomap_map_trace(XFS_IOMAP_ALLOC_MAP, io, | 254 | xfs_iomap_map_trace(XFS_IOMAP_ALLOC_MAP, ip, |
269 | offset, count, iomapp, &imap, flags); | 255 | offset, count, iomapp, &imap, flags); |
270 | } | 256 | } |
271 | iomap_flags = IOMAP_NEW; | 257 | iomap_flags = IOMAP_NEW; |
272 | break; | 258 | break; |
273 | case BMAPI_ALLOCATE: | 259 | case BMAPI_ALLOCATE: |
274 | /* If we found an extent, return it */ | 260 | /* If we found an extent, return it */ |
275 | XFS_IUNLOCK(mp, io, lockmode); | 261 | xfs_iunlock(ip, lockmode); |
276 | lockmode = 0; | 262 | lockmode = 0; |
277 | 263 | ||
278 | if (nimaps && !ISNULLSTARTBLOCK(imap.br_startblock)) { | 264 | if (nimaps && !ISNULLSTARTBLOCK(imap.br_startblock)) { |
279 | xfs_iomap_map_trace(XFS_IOMAP_WRITE_MAP, io, | 265 | xfs_iomap_map_trace(XFS_IOMAP_WRITE_MAP, ip, |
280 | offset, count, iomapp, &imap, flags); | 266 | offset, count, iomapp, &imap, flags); |
281 | break; | 267 | break; |
282 | } | 268 | } |
283 | 269 | ||
284 | error = XFS_IOMAP_WRITE_ALLOCATE(mp, io, offset, count, | 270 | error = xfs_iomap_write_allocate(ip, offset, count, |
285 | &imap, &nimaps); | 271 | &imap, &nimaps); |
286 | break; | 272 | break; |
287 | case BMAPI_UNWRITTEN: | ||
288 | lockmode = 0; | ||
289 | error = XFS_IOMAP_WRITE_UNWRITTEN(mp, io, offset, count); | ||
290 | nimaps = 0; | ||
291 | break; | ||
292 | } | 273 | } |
293 | 274 | ||
294 | if (nimaps) { | 275 | if (nimaps) { |
295 | *niomaps = xfs_imap_to_bmap(io, offset, &imap, | 276 | *niomaps = xfs_imap_to_bmap(ip, offset, &imap, |
296 | iomapp, nimaps, *niomaps, iomap_flags); | 277 | iomapp, nimaps, *niomaps, iomap_flags); |
297 | } else if (niomaps) { | 278 | } else if (niomaps) { |
298 | *niomaps = 0; | 279 | *niomaps = 0; |
@@ -300,14 +281,15 @@ phase2: | |||
300 | 281 | ||
301 | out: | 282 | out: |
302 | if (lockmode) | 283 | if (lockmode) |
303 | XFS_IUNLOCK(mp, io, lockmode); | 284 | xfs_iunlock(ip, lockmode); |
304 | return XFS_ERROR(error); | 285 | return XFS_ERROR(error); |
305 | } | 286 | } |
306 | 287 | ||
288 | |||
307 | STATIC int | 289 | STATIC int |
308 | xfs_iomap_eof_align_last_fsb( | 290 | xfs_iomap_eof_align_last_fsb( |
309 | xfs_mount_t *mp, | 291 | xfs_mount_t *mp, |
310 | xfs_iocore_t *io, | 292 | xfs_inode_t *ip, |
311 | xfs_fsize_t isize, | 293 | xfs_fsize_t isize, |
312 | xfs_extlen_t extsize, | 294 | xfs_extlen_t extsize, |
313 | xfs_fileoff_t *last_fsb) | 295 | xfs_fileoff_t *last_fsb) |
@@ -316,7 +298,7 @@ xfs_iomap_eof_align_last_fsb( | |||
316 | xfs_extlen_t align; | 298 | xfs_extlen_t align; |
317 | int eof, error; | 299 | int eof, error; |
318 | 300 | ||
319 | if (io->io_flags & XFS_IOCORE_RT) | 301 | if (XFS_IS_REALTIME_INODE(ip)) |
320 | ; | 302 | ; |
321 | /* | 303 | /* |
322 | * If mounted with the "-o swalloc" option, roundup the allocation | 304 | * If mounted with the "-o swalloc" option, roundup the allocation |
@@ -347,7 +329,7 @@ xfs_iomap_eof_align_last_fsb( | |||
347 | } | 329 | } |
348 | 330 | ||
349 | if (new_last_fsb) { | 331 | if (new_last_fsb) { |
350 | error = XFS_BMAP_EOF(mp, io, new_last_fsb, XFS_DATA_FORK, &eof); | 332 | error = xfs_bmap_eof(ip, new_last_fsb, XFS_DATA_FORK, &eof); |
351 | if (error) | 333 | if (error) |
352 | return error; | 334 | return error; |
353 | if (eof) | 335 | if (eof) |
@@ -416,7 +398,6 @@ xfs_iomap_write_direct( | |||
416 | int found) | 398 | int found) |
417 | { | 399 | { |
418 | xfs_mount_t *mp = ip->i_mount; | 400 | xfs_mount_t *mp = ip->i_mount; |
419 | xfs_iocore_t *io = &ip->i_iocore; | ||
420 | xfs_fileoff_t offset_fsb; | 401 | xfs_fileoff_t offset_fsb; |
421 | xfs_fileoff_t last_fsb; | 402 | xfs_fileoff_t last_fsb; |
422 | xfs_filblks_t count_fsb, resaligned; | 403 | xfs_filblks_t count_fsb, resaligned; |
@@ -446,13 +427,13 @@ xfs_iomap_write_direct( | |||
446 | extsz = xfs_get_extsz_hint(ip); | 427 | extsz = xfs_get_extsz_hint(ip); |
447 | 428 | ||
448 | isize = ip->i_size; | 429 | isize = ip->i_size; |
449 | if (io->io_new_size > isize) | 430 | if (ip->i_new_size > isize) |
450 | isize = io->io_new_size; | 431 | isize = ip->i_new_size; |
451 | 432 | ||
452 | offset_fsb = XFS_B_TO_FSBT(mp, offset); | 433 | offset_fsb = XFS_B_TO_FSBT(mp, offset); |
453 | last_fsb = XFS_B_TO_FSB(mp, ((xfs_ufsize_t)(offset + count))); | 434 | last_fsb = XFS_B_TO_FSB(mp, ((xfs_ufsize_t)(offset + count))); |
454 | if ((offset + count) > isize) { | 435 | if ((offset + count) > isize) { |
455 | error = xfs_iomap_eof_align_last_fsb(mp, io, isize, extsz, | 436 | error = xfs_iomap_eof_align_last_fsb(mp, ip, isize, extsz, |
456 | &last_fsb); | 437 | &last_fsb); |
457 | if (error) | 438 | if (error) |
458 | goto error_out; | 439 | goto error_out; |
@@ -519,7 +500,7 @@ xfs_iomap_write_direct( | |||
519 | */ | 500 | */ |
520 | XFS_BMAP_INIT(&free_list, &firstfsb); | 501 | XFS_BMAP_INIT(&free_list, &firstfsb); |
521 | nimaps = 1; | 502 | nimaps = 1; |
522 | error = XFS_BMAPI(mp, tp, io, offset_fsb, count_fsb, bmapi_flag, | 503 | error = xfs_bmapi(tp, ip, offset_fsb, count_fsb, bmapi_flag, |
523 | &firstfsb, 0, &imap, &nimaps, &free_list, NULL); | 504 | &firstfsb, 0, &imap, &nimaps, &free_list, NULL); |
524 | if (error) | 505 | if (error) |
525 | goto error0; | 506 | goto error0; |
@@ -542,7 +523,8 @@ xfs_iomap_write_direct( | |||
542 | goto error_out; | 523 | goto error_out; |
543 | } | 524 | } |
544 | 525 | ||
545 | if (unlikely(!imap.br_startblock && !(io->io_flags & XFS_IOCORE_RT))) { | 526 | if (unlikely(!imap.br_startblock && |
527 | !(XFS_IS_REALTIME_INODE(ip)))) { | ||
546 | error = xfs_cmn_err_fsblock_zero(ip, &imap); | 528 | error = xfs_cmn_err_fsblock_zero(ip, &imap); |
547 | goto error_out; | 529 | goto error_out; |
548 | } | 530 | } |
@@ -577,7 +559,7 @@ error_out: | |||
577 | STATIC int | 559 | STATIC int |
578 | xfs_iomap_eof_want_preallocate( | 560 | xfs_iomap_eof_want_preallocate( |
579 | xfs_mount_t *mp, | 561 | xfs_mount_t *mp, |
580 | xfs_iocore_t *io, | 562 | xfs_inode_t *ip, |
581 | xfs_fsize_t isize, | 563 | xfs_fsize_t isize, |
582 | xfs_off_t offset, | 564 | xfs_off_t offset, |
583 | size_t count, | 565 | size_t count, |
@@ -604,7 +586,7 @@ xfs_iomap_eof_want_preallocate( | |||
604 | while (count_fsb > 0) { | 586 | while (count_fsb > 0) { |
605 | imaps = nimaps; | 587 | imaps = nimaps; |
606 | firstblock = NULLFSBLOCK; | 588 | firstblock = NULLFSBLOCK; |
607 | error = XFS_BMAPI(mp, NULL, io, start_fsb, count_fsb, 0, | 589 | error = xfs_bmapi(NULL, ip, start_fsb, count_fsb, 0, |
608 | &firstblock, 0, imap, &imaps, NULL, NULL); | 590 | &firstblock, 0, imap, &imaps, NULL, NULL); |
609 | if (error) | 591 | if (error) |
610 | return error; | 592 | return error; |
@@ -630,7 +612,6 @@ xfs_iomap_write_delay( | |||
630 | int *nmaps) | 612 | int *nmaps) |
631 | { | 613 | { |
632 | xfs_mount_t *mp = ip->i_mount; | 614 | xfs_mount_t *mp = ip->i_mount; |
633 | xfs_iocore_t *io = &ip->i_iocore; | ||
634 | xfs_fileoff_t offset_fsb; | 615 | xfs_fileoff_t offset_fsb; |
635 | xfs_fileoff_t last_fsb; | 616 | xfs_fileoff_t last_fsb; |
636 | xfs_off_t aligned_offset; | 617 | xfs_off_t aligned_offset; |
@@ -658,10 +639,10 @@ xfs_iomap_write_delay( | |||
658 | 639 | ||
659 | retry: | 640 | retry: |
660 | isize = ip->i_size; | 641 | isize = ip->i_size; |
661 | if (io->io_new_size > isize) | 642 | if (ip->i_new_size > isize) |
662 | isize = io->io_new_size; | 643 | isize = ip->i_new_size; |
663 | 644 | ||
664 | error = xfs_iomap_eof_want_preallocate(mp, io, isize, offset, count, | 645 | error = xfs_iomap_eof_want_preallocate(mp, ip, isize, offset, count, |
665 | ioflag, imap, XFS_WRITE_IMAPS, &prealloc); | 646 | ioflag, imap, XFS_WRITE_IMAPS, &prealloc); |
666 | if (error) | 647 | if (error) |
667 | return error; | 648 | return error; |
@@ -675,7 +656,7 @@ retry: | |||
675 | } | 656 | } |
676 | 657 | ||
677 | if (prealloc || extsz) { | 658 | if (prealloc || extsz) { |
678 | error = xfs_iomap_eof_align_last_fsb(mp, io, isize, extsz, | 659 | error = xfs_iomap_eof_align_last_fsb(mp, ip, isize, extsz, |
679 | &last_fsb); | 660 | &last_fsb); |
680 | if (error) | 661 | if (error) |
681 | return error; | 662 | return error; |
@@ -683,7 +664,7 @@ retry: | |||
683 | 664 | ||
684 | nimaps = XFS_WRITE_IMAPS; | 665 | nimaps = XFS_WRITE_IMAPS; |
685 | firstblock = NULLFSBLOCK; | 666 | firstblock = NULLFSBLOCK; |
686 | error = XFS_BMAPI(mp, NULL, io, offset_fsb, | 667 | error = xfs_bmapi(NULL, ip, offset_fsb, |
687 | (xfs_filblks_t)(last_fsb - offset_fsb), | 668 | (xfs_filblks_t)(last_fsb - offset_fsb), |
688 | XFS_BMAPI_DELAY | XFS_BMAPI_WRITE | | 669 | XFS_BMAPI_DELAY | XFS_BMAPI_WRITE | |
689 | XFS_BMAPI_ENTIRE, &firstblock, 1, imap, | 670 | XFS_BMAPI_ENTIRE, &firstblock, 1, imap, |
@@ -697,7 +678,7 @@ retry: | |||
697 | */ | 678 | */ |
698 | if (nimaps == 0) { | 679 | if (nimaps == 0) { |
699 | xfs_iomap_enter_trace(XFS_IOMAP_WRITE_NOSPACE, | 680 | xfs_iomap_enter_trace(XFS_IOMAP_WRITE_NOSPACE, |
700 | io, offset, count); | 681 | ip, offset, count); |
701 | if (xfs_flush_space(ip, &fsynced, &ioflag)) | 682 | if (xfs_flush_space(ip, &fsynced, &ioflag)) |
702 | return XFS_ERROR(ENOSPC); | 683 | return XFS_ERROR(ENOSPC); |
703 | 684 | ||
@@ -705,7 +686,8 @@ retry: | |||
705 | goto retry; | 686 | goto retry; |
706 | } | 687 | } |
707 | 688 | ||
708 | if (unlikely(!imap[0].br_startblock && !(io->io_flags & XFS_IOCORE_RT))) | 689 | if (unlikely(!imap[0].br_startblock && |
690 | !(XFS_IS_REALTIME_INODE(ip)))) | ||
709 | return xfs_cmn_err_fsblock_zero(ip, &imap[0]); | 691 | return xfs_cmn_err_fsblock_zero(ip, &imap[0]); |
710 | 692 | ||
711 | *ret_imap = imap[0]; | 693 | *ret_imap = imap[0]; |
@@ -720,6 +702,9 @@ retry: | |||
720 | * the originating callers request. | 702 | * the originating callers request. |
721 | * | 703 | * |
722 | * Called without a lock on the inode. | 704 | * Called without a lock on the inode. |
705 | * | ||
706 | * We no longer bother to look at the incoming map - all we have to | ||
707 | * guarantee is that whatever we allocate fills the required range. | ||
723 | */ | 708 | */ |
724 | int | 709 | int |
725 | xfs_iomap_write_allocate( | 710 | xfs_iomap_write_allocate( |
@@ -730,15 +715,14 @@ xfs_iomap_write_allocate( | |||
730 | int *retmap) | 715 | int *retmap) |
731 | { | 716 | { |
732 | xfs_mount_t *mp = ip->i_mount; | 717 | xfs_mount_t *mp = ip->i_mount; |
733 | xfs_iocore_t *io = &ip->i_iocore; | ||
734 | xfs_fileoff_t offset_fsb, last_block; | 718 | xfs_fileoff_t offset_fsb, last_block; |
735 | xfs_fileoff_t end_fsb, map_start_fsb; | 719 | xfs_fileoff_t end_fsb, map_start_fsb; |
736 | xfs_fsblock_t first_block; | 720 | xfs_fsblock_t first_block; |
737 | xfs_bmap_free_t free_list; | 721 | xfs_bmap_free_t free_list; |
738 | xfs_filblks_t count_fsb; | 722 | xfs_filblks_t count_fsb; |
739 | xfs_bmbt_irec_t imap[XFS_STRAT_WRITE_IMAPS]; | 723 | xfs_bmbt_irec_t imap; |
740 | xfs_trans_t *tp; | 724 | xfs_trans_t *tp; |
741 | int i, nimaps, committed; | 725 | int nimaps, committed; |
742 | int error = 0; | 726 | int error = 0; |
743 | int nres; | 727 | int nres; |
744 | 728 | ||
@@ -785,13 +769,38 @@ xfs_iomap_write_allocate( | |||
785 | 769 | ||
786 | XFS_BMAP_INIT(&free_list, &first_block); | 770 | XFS_BMAP_INIT(&free_list, &first_block); |
787 | 771 | ||
788 | nimaps = XFS_STRAT_WRITE_IMAPS; | ||
789 | /* | 772 | /* |
790 | * Ensure we don't go beyond eof - it is possible | 773 | * it is possible that the extents have changed since |
791 | * the extents changed since we did the read call, | 774 | * we did the read call as we dropped the ilock for a |
792 | * we dropped the ilock in the interim. | 775 | * while. We have to be careful about truncates or hole |
776 | * punchs here - we are not allowed to allocate | ||
777 | * non-delalloc blocks here. | ||
778 | * | ||
779 | * The only protection against truncation is the pages | ||
780 | * for the range we are being asked to convert are | ||
781 | * locked and hence a truncate will block on them | ||
782 | * first. | ||
783 | * | ||
784 | * As a result, if we go beyond the range we really | ||
785 | * need and hit an delalloc extent boundary followed by | ||
786 | * a hole while we have excess blocks in the map, we | ||
787 | * will fill the hole incorrectly and overrun the | ||
788 | * transaction reservation. | ||
789 | * | ||
790 | * Using a single map prevents this as we are forced to | ||
791 | * check each map we look for overlap with the desired | ||
792 | * range and abort as soon as we find it. Also, given | ||
793 | * that we only return a single map, having one beyond | ||
794 | * what we can return is probably a bit silly. | ||
795 | * | ||
796 | * We also need to check that we don't go beyond EOF; | ||
797 | * this is a truncate optimisation as a truncate sets | ||
798 | * the new file size before block on the pages we | ||
799 | * currently have locked under writeback. Because they | ||
800 | * are about to be tossed, we don't need to write them | ||
801 | * back.... | ||
793 | */ | 802 | */ |
794 | 803 | nimaps = 1; | |
795 | end_fsb = XFS_B_TO_FSB(mp, ip->i_size); | 804 | end_fsb = XFS_B_TO_FSB(mp, ip->i_size); |
796 | xfs_bmap_last_offset(NULL, ip, &last_block, | 805 | xfs_bmap_last_offset(NULL, ip, &last_block, |
797 | XFS_DATA_FORK); | 806 | XFS_DATA_FORK); |
@@ -805,9 +814,9 @@ xfs_iomap_write_allocate( | |||
805 | } | 814 | } |
806 | 815 | ||
807 | /* Go get the actual blocks */ | 816 | /* Go get the actual blocks */ |
808 | error = XFS_BMAPI(mp, tp, io, map_start_fsb, count_fsb, | 817 | error = xfs_bmapi(tp, ip, map_start_fsb, count_fsb, |
809 | XFS_BMAPI_WRITE, &first_block, 1, | 818 | XFS_BMAPI_WRITE, &first_block, 1, |
810 | imap, &nimaps, &free_list, NULL); | 819 | &imap, &nimaps, &free_list, NULL); |
811 | if (error) | 820 | if (error) |
812 | goto trans_cancel; | 821 | goto trans_cancel; |
813 | 822 | ||
@@ -826,27 +835,24 @@ xfs_iomap_write_allocate( | |||
826 | * See if we were able to allocate an extent that | 835 | * See if we were able to allocate an extent that |
827 | * covers at least part of the callers request | 836 | * covers at least part of the callers request |
828 | */ | 837 | */ |
829 | for (i = 0; i < nimaps; i++) { | 838 | if (unlikely(!imap.br_startblock && |
830 | if (unlikely(!imap[i].br_startblock && | 839 | XFS_IS_REALTIME_INODE(ip))) |
831 | !(io->io_flags & XFS_IOCORE_RT))) | 840 | return xfs_cmn_err_fsblock_zero(ip, &imap); |
832 | return xfs_cmn_err_fsblock_zero(ip, &imap[i]); | 841 | if ((offset_fsb >= imap.br_startoff) && |
833 | if ((offset_fsb >= imap[i].br_startoff) && | 842 | (offset_fsb < (imap.br_startoff + |
834 | (offset_fsb < (imap[i].br_startoff + | 843 | imap.br_blockcount))) { |
835 | imap[i].br_blockcount))) { | 844 | *map = imap; |
836 | *map = imap[i]; | 845 | *retmap = 1; |
837 | *retmap = 1; | 846 | XFS_STATS_INC(xs_xstrat_quick); |
838 | XFS_STATS_INC(xs_xstrat_quick); | 847 | return 0; |
839 | return 0; | ||
840 | } | ||
841 | count_fsb -= imap[i].br_blockcount; | ||
842 | } | 848 | } |
843 | 849 | ||
844 | /* So far we have not mapped the requested part of the | 850 | /* |
851 | * So far we have not mapped the requested part of the | ||
845 | * file, just surrounding data, try again. | 852 | * file, just surrounding data, try again. |
846 | */ | 853 | */ |
847 | nimaps--; | 854 | count_fsb -= imap.br_blockcount; |
848 | map_start_fsb = imap[nimaps].br_startoff + | 855 | map_start_fsb = imap.br_startoff + imap.br_blockcount; |
849 | imap[nimaps].br_blockcount; | ||
850 | } | 856 | } |
851 | 857 | ||
852 | trans_cancel: | 858 | trans_cancel: |
@@ -864,7 +870,6 @@ xfs_iomap_write_unwritten( | |||
864 | size_t count) | 870 | size_t count) |
865 | { | 871 | { |
866 | xfs_mount_t *mp = ip->i_mount; | 872 | xfs_mount_t *mp = ip->i_mount; |
867 | xfs_iocore_t *io = &ip->i_iocore; | ||
868 | xfs_fileoff_t offset_fsb; | 873 | xfs_fileoff_t offset_fsb; |
869 | xfs_filblks_t count_fsb; | 874 | xfs_filblks_t count_fsb; |
870 | xfs_filblks_t numblks_fsb; | 875 | xfs_filblks_t numblks_fsb; |
@@ -877,8 +882,7 @@ xfs_iomap_write_unwritten( | |||
877 | int committed; | 882 | int committed; |
878 | int error; | 883 | int error; |
879 | 884 | ||
880 | xfs_iomap_enter_trace(XFS_IOMAP_UNWRITTEN, | 885 | xfs_iomap_enter_trace(XFS_IOMAP_UNWRITTEN, ip, offset, count); |
881 | &ip->i_iocore, offset, count); | ||
882 | 886 | ||
883 | offset_fsb = XFS_B_TO_FSBT(mp, offset); | 887 | offset_fsb = XFS_B_TO_FSBT(mp, offset); |
884 | count_fsb = XFS_B_TO_FSB(mp, (xfs_ufsize_t)offset + count); | 888 | count_fsb = XFS_B_TO_FSB(mp, (xfs_ufsize_t)offset + count); |
@@ -912,7 +916,7 @@ xfs_iomap_write_unwritten( | |||
912 | */ | 916 | */ |
913 | XFS_BMAP_INIT(&free_list, &firstfsb); | 917 | XFS_BMAP_INIT(&free_list, &firstfsb); |
914 | nimaps = 1; | 918 | nimaps = 1; |
915 | error = XFS_BMAPI(mp, tp, io, offset_fsb, count_fsb, | 919 | error = xfs_bmapi(tp, ip, offset_fsb, count_fsb, |
916 | XFS_BMAPI_WRITE|XFS_BMAPI_CONVERT, &firstfsb, | 920 | XFS_BMAPI_WRITE|XFS_BMAPI_CONVERT, &firstfsb, |
917 | 1, &imap, &nimaps, &free_list, NULL); | 921 | 1, &imap, &nimaps, &free_list, NULL); |
918 | if (error) | 922 | if (error) |
@@ -928,7 +932,7 @@ xfs_iomap_write_unwritten( | |||
928 | return XFS_ERROR(error); | 932 | return XFS_ERROR(error); |
929 | 933 | ||
930 | if (unlikely(!imap.br_startblock && | 934 | if (unlikely(!imap.br_startblock && |
931 | !(io->io_flags & XFS_IOCORE_RT))) | 935 | !(XFS_IS_REALTIME_INODE(ip)))) |
932 | return xfs_cmn_err_fsblock_zero(ip, &imap); | 936 | return xfs_cmn_err_fsblock_zero(ip, &imap); |
933 | 937 | ||
934 | if ((numblks_fsb = imap.br_blockcount) == 0) { | 938 | if ((numblks_fsb = imap.br_blockcount) == 0) { |