X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=fs%2Fxfs%2Fxfs_iomap.c;h=7e1c1290a515bdbfcb0c3c8490a1153b8385170a;hb=d939d46ba7caa14e960be18e18f5c07be8806d7a;hp=c6083d81a667d1896d7c8a1d7c90526fb1c2eeee;hpb=86090fcac5e27b630656fe3d963a6b80e26dac44;p=linux-2.6.git diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c index c6083d81a..7e1c1290a 100644 --- a/fs/xfs/xfs_iomap.c +++ b/fs/xfs/xfs_iomap.c @@ -577,25 +577,70 @@ retry: */ if (!(ioflag & BMAPI_SYNC) && ((offset + count) > ip->i_d.di_size)) { xfs_off_t aligned_offset; + xfs_filblks_t count_fsb; unsigned int iosize; xfs_fileoff_t ioalign; + int n; + xfs_fileoff_t start_fsb; + /* + * If there are any real blocks past eof, then don't + * do any speculative allocation. + */ + start_fsb = XFS_B_TO_FSBT(mp, + ((xfs_ufsize_t)(offset + count - 1))); + count_fsb = XFS_B_TO_FSB(mp, (xfs_ufsize_t)XFS_MAXIOFFSET(mp)); + while (count_fsb > 0) { + nimaps = XFS_WRITE_IMAPS; + error = XFS_BMAPI(mp, NULL, io, start_fsb, count_fsb, + 0, &firstblock, 0, imap, &nimaps, NULL); + if (error) { + return error; + } + for (n = 0; n < nimaps; n++) { + if ((imap[n].br_startblock != HOLESTARTBLOCK) && + (imap[n].br_startblock != DELAYSTARTBLOCK)) { + goto write_map; + } + start_fsb += imap[n].br_blockcount; + count_fsb -= imap[n].br_blockcount; + } + } iosize = mp->m_writeio_blocks; aligned_offset = XFS_WRITEIO_ALIGN(mp, (offset + count - 1)); ioalign = XFS_B_TO_FSBT(mp, aligned_offset); last_fsb = ioalign + iosize; aeof = 1; } - +write_map: nimaps = XFS_WRITE_IMAPS; firstblock = NULLFSBLOCK; + /* + * If mounted with the "-o swalloc" option, roundup the allocation + * request to a stripe width boundary if the file size is >= + * stripe width and we are allocating past the allocation eof. + */ + if (mp->m_swidth && (mp->m_flags & XFS_MOUNT_SWALLOC) + && (isize >= XFS_FSB_TO_B(mp, mp->m_swidth)) && aeof) { + int eof; + xfs_fileoff_t new_last_fsb; + + new_last_fsb = roundup_64(last_fsb, mp->m_swidth); + error = xfs_bmap_eof(ip, new_last_fsb, XFS_DATA_FORK, &eof); + if (error) { + return error; + } + if (eof) { + last_fsb = new_last_fsb; + } /* * Roundup the allocation request to a stripe unit (m_dalign) boundary * if the file size is >= stripe unit size, and we are allocating past * the allocation eof. */ - if (mp->m_dalign && (isize >= XFS_FSB_TO_B(mp, mp->m_dalign)) && aeof) { + } else if (mp->m_dalign && (isize >= XFS_FSB_TO_B(mp, mp->m_dalign)) + && aeof) { int eof; xfs_fileoff_t new_last_fsb; new_last_fsb = roundup_64(last_fsb, mp->m_dalign);