@@ -352,22 +352,10 @@ xfs_quota_calc_throttle(
352
352
}
353
353
354
354
/*
355
- * If we are doing a write at the end of the file and there are no allocations
356
- * past this one, then extend the allocation out to the file system's write
357
- * iosize.
358
- *
359
355
* If we don't have a user specified preallocation size, dynamically increase
360
356
* the preallocation size as the size of the file grows. Cap the maximum size
361
357
* at a single extent or less if the filesystem is near full. The closer the
362
- * filesystem is to full, the smaller the maximum prealocation.
363
- *
364
- * As an exception we don't do any preallocation at all if the file is smaller
365
- * than the minimum preallocation and we are using the default dynamic
366
- * preallocation scheme, as it is likely this is the only write to the file that
367
- * is going to be done.
368
- *
369
- * We clean up any extra space left over when the file is closed in
370
- * xfs_inactive().
358
+ * filesystem is to being full, the smaller the maximum preallocation.
371
359
*/
372
360
STATIC xfs_fsblock_t
373
361
xfs_iomap_prealloc_size (
@@ -389,41 +377,28 @@ xfs_iomap_prealloc_size(
389
377
int shift = 0 ;
390
378
int qshift = 0 ;
391
379
392
- if (offset + count <= XFS_ISIZE (ip ))
393
- return 0 ;
394
-
395
- if (!(mp -> m_flags & XFS_MOUNT_ALLOCSIZE ) &&
396
- (XFS_ISIZE (ip ) < XFS_FSB_TO_B (mp , mp -> m_allocsize_blocks )))
380
+ /*
381
+ * As an exception we don't do any preallocation at all if the file is
382
+ * smaller than the minimum preallocation and we are using the default
383
+ * dynamic preallocation scheme, as it is likely this is the only write
384
+ * to the file that is going to be done.
385
+ */
386
+ if (XFS_ISIZE (ip ) < XFS_FSB_TO_B (mp , mp -> m_allocsize_blocks ))
397
387
return 0 ;
398
388
399
389
/*
400
- * If an explicit allocsize is set, the file is small, or we
401
- * are writing behind a hole, then use the minimum prealloc:
390
+ * Use the minimum preallocation size for small files or if we are
391
+ * writing right after a hole.
402
392
*/
403
- if ((mp -> m_flags & XFS_MOUNT_ALLOCSIZE ) ||
404
- XFS_ISIZE (ip ) < XFS_FSB_TO_B (mp , mp -> m_dalign ) ||
393
+ if (XFS_ISIZE (ip ) < XFS_FSB_TO_B (mp , mp -> m_dalign ) ||
405
394
!xfs_iext_prev_extent (ifp , & ncur , & prev ) ||
406
395
prev .br_startoff + prev .br_blockcount < offset_fsb )
407
396
return mp -> m_allocsize_blocks ;
408
397
409
398
/*
410
- * Determine the initial size of the preallocation. We are beyond the
411
- * current EOF here, but we need to take into account whether this is
412
- * a sparse write or an extending write when determining the
413
- * preallocation size. Hence we need to look up the extent that ends
414
- * at the current write offset and use the result to determine the
415
- * preallocation size.
416
- *
417
- * If the extent is a hole, then preallocation is essentially disabled.
418
- * Otherwise we take the size of the preceding data extents as the basis
419
- * for the preallocation size. Note that we don't care if the previous
420
- * extents are written or not.
421
- *
422
- * If the size of the extents is greater than half the maximum extent
423
- * length, then use the current offset as the basis. This ensures that
424
- * for large files the preallocation size always extends to MAXEXTLEN
425
- * rather than falling short due to things like stripe unit/width
426
- * alignment of real extents.
399
+ * Take the size of the preceding data extents as the basis for the
400
+ * preallocation size. Note that we don't care if the previous extents
401
+ * are written or not.
427
402
*/
428
403
plen = prev .br_blockcount ;
429
404
while (xfs_iext_prev_extent (ifp , & ncur , & got )) {
@@ -435,19 +410,25 @@ xfs_iomap_prealloc_size(
435
410
plen += got .br_blockcount ;
436
411
prev = got ;
437
412
}
413
+
414
+ /*
415
+ * If the size of the extents is greater than half the maximum extent
416
+ * length, then use the current offset as the basis. This ensures that
417
+ * for large files the preallocation size always extends to MAXEXTLEN
418
+ * rather than falling short due to things like stripe unit/width
419
+ * alignment of real extents.
420
+ */
438
421
alloc_blocks = plen * 2 ;
439
422
if (alloc_blocks > MAXEXTLEN )
440
423
alloc_blocks = XFS_B_TO_FSB (mp , offset );
441
- if (!alloc_blocks )
442
- goto check_writeio ;
443
424
qblocks = alloc_blocks ;
444
425
445
426
/*
446
427
* MAXEXTLEN is not a power of two value but we round the prealloc down
447
428
* to the nearest power of two value after throttling. To prevent the
448
- * round down from unconditionally reducing the maximum supported prealloc
449
- * size, we round up first, apply appropriate throttling, round down and
450
- * cap the value to MAXEXTLEN.
429
+ * round down from unconditionally reducing the maximum supported
430
+ * prealloc size, we round up first, apply appropriate throttling,
431
+ * round down and cap the value to MAXEXTLEN.
451
432
*/
452
433
alloc_blocks = XFS_FILEOFF_MIN (roundup_pow_of_two (MAXEXTLEN ),
453
434
alloc_blocks );
@@ -508,7 +489,6 @@ xfs_iomap_prealloc_size(
508
489
*/
509
490
while (alloc_blocks && alloc_blocks >= freesp )
510
491
alloc_blocks >>= 4 ;
511
- check_writeio :
512
492
if (alloc_blocks < mp -> m_allocsize_blocks )
513
493
alloc_blocks = mp -> m_allocsize_blocks ;
514
494
trace_xfs_iomap_prealloc_size (ip , alloc_blocks , shift ,
@@ -975,9 +955,16 @@ xfs_buffered_write_iomap_begin(
975
955
if (error )
976
956
goto out_unlock ;
977
957
978
- if (eof ) {
979
- prealloc_blocks = xfs_iomap_prealloc_size (ip , allocfork , offset ,
980
- count , & icur );
958
+ if (eof && offset + count > XFS_ISIZE (ip )) {
959
+ /*
960
+ * Determine the initial size of the preallocation.
961
+ * We clean up any extra preallocation when the file is closed.
962
+ */
963
+ if (mp -> m_flags & XFS_MOUNT_ALLOCSIZE )
964
+ prealloc_blocks = mp -> m_allocsize_blocks ;
965
+ else
966
+ prealloc_blocks = xfs_iomap_prealloc_size (ip , allocfork ,
967
+ offset , count , & icur );
981
968
if (prealloc_blocks ) {
982
969
xfs_extlen_t align ;
983
970
xfs_off_t end_offset ;
0 commit comments