aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs/xfs_iomap.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@woody.linux-foundation.org>2008-02-07 22:12:12 -0500
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2008-02-07 22:12:12 -0500
commit0b61a2ba5dfd1620731e717d686e6ade657fd975 (patch)
treedea84efd43934a7d6139048f87c4ba86d68d4b6d /fs/xfs/xfs_iomap.c
parenta13ff0bb3feda8b1fcffc69951320277ed7c4101 (diff)
parentde2eeea609b55e8c3994133a565b39edeaaaaf69 (diff)
Merge branch 'for-linus' of git://oss.sgi.com:8090/xfs/xfs-2.6
* 'for-linus' of git://oss.sgi.com:8090/xfs/xfs-2.6: (62 commits) [XFS] add __init/__exit mark to specific init/cleanup functions [XFS] Fix oops in xfs_file_readdir() [XFS] kill xfs_root [XFS] keep i_nlink updated and use proper accessors [XFS] stop updating inode->i_blocks [XFS] Make xfs_ail_check check less by default [XFS] Move AIL pushing into it's own thread [XFS] use generic_permission [XFS] stop re-checking permissions in xfs_swapext [XFS] clean up xfs_swapext [XFS] remove permission check from xfs_change_file_space [XFS] prevent panic during log recovery due to bogus op_hdr length [XFS] Cleanup various fid related bits: [XFS] Fix xfs_lowbit64 [XFS] Remove CFORK macros and use code directly in IFORK and DFORK macros. [XFS] kill superflous buffer locking (2nd attempt) [XFS] Use kernel-supplied "roundup_pow_of_two" for simplicity [XFS] Remove the BPCSHIFT and NB* based macros from XFS. [XFS] Remove bogus assert [XFS] optimize XFS_IS_REALTIME_INODE w/o realtime config ...
Diffstat (limited to 'fs/xfs/xfs_iomap.c')
-rw-r--r--fs/xfs/xfs_iomap.c212
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 @@
53void 53void
54xfs_iomap_enter_trace( 54xfs_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(
84void 82void
85xfs_iomap_map_trace( 83xfs_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
127STATIC int 123STATIC int
128xfs_imap_to_bmap( 124xfs_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
173int 168int
174xfs_iomap( 169xfs_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
248phase2: 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
301out: 282out:
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
307STATIC int 289STATIC int
308xfs_iomap_eof_align_last_fsb( 290xfs_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:
577STATIC int 559STATIC int
578xfs_iomap_eof_want_preallocate( 560xfs_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
659retry: 640retry:
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 */
724int 709int
725xfs_iomap_write_allocate( 710xfs_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
852trans_cancel: 858trans_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) {