Diff for /xfs-linux/xfs_iomap.c between versions 1.59 and 1.60

version 1.59, 2007/09/21 16:10:12 version 1.60, 2007/11/02 03:11:36
Line 702  retry: Line 702  retry:
  * the originating callers request.   * the originating callers request.
  *   *
  * Called without a lock on the inode.   * Called without a lock on the inode.
    *
    * We no longer bother to look at the incoming map - all we have to
    * guarantee is that whatever we allocate fills the required range.
  */   */
 int  int
 xfs_iomap_write_allocate(  xfs_iomap_write_allocate(
Line 717  xfs_iomap_write_allocate( Line 720  xfs_iomap_write_allocate(
         xfs_fsblock_t   first_block;          xfs_fsblock_t   first_block;
         xfs_bmap_free_t free_list;          xfs_bmap_free_t free_list;
         xfs_filblks_t   count_fsb;          xfs_filblks_t   count_fsb;
         xfs_bmbt_irec_t imap[XFS_STRAT_WRITE_IMAPS];          xfs_bmbt_irec_t imap;
         xfs_trans_t     *tp;          xfs_trans_t     *tp;
         int             i, nimaps, committed;          int             nimaps, committed;
         int             error = 0;          int             error = 0;
         int             nres;          int             nres;
   
Line 766  xfs_iomap_write_allocate( Line 769  xfs_iomap_write_allocate(
   
                         XFS_BMAP_INIT(&free_list, &first_block);                          XFS_BMAP_INIT(&free_list, &first_block);
   
                         nimaps = XFS_STRAT_WRITE_IMAPS;  
                         /*                          /*
                          * Ensure we don't go beyond eof - it is possible                           * it is possible that the extents have changed since
                          * the extents changed since we did the read call,                           * we did the read call as we dropped the ilock for a
                          * we dropped the ilock in the interim.                           * while. We have to be careful about truncates or hole
                            * punchs here - we are not allowed to allocate
                            * non-delalloc blocks here.
                            *
                            * The only protection against truncation is the pages
                            * for the range we are being asked to convert are
                            * locked and hence a truncate will block on them
                            * first.
                            *
                            * As a result, if we go beyond the range we really
                            * need and hit an delalloc extent boundary followed by
                            * a hole while we have excess blocks in the map, we
                            * will fill the hole incorrectly and overrun the
                            * transaction reservation.
                            *
                            * Using a single map prevents this as we are forced to
                            * check each map we look for overlap with the desired
                            * range and abort as soon as we find it. Also, given
                            * that we only return a single map, having one beyond
                            * what we can return is probably a bit silly.
                            *
                            * We also need to check that we don't go beyond EOF;
                            * this is a truncate optimisation as a truncate sets
                            * the new file size before block on the pages we
                            * currently have locked under writeback. Because they
                            * are about to be tossed, we don't need to write them
                            * back....
                          */                           */
                           nimaps = 1;
                         end_fsb = XFS_B_TO_FSB(mp, ip->i_size);                          end_fsb = XFS_B_TO_FSB(mp, ip->i_size);
                         xfs_bmap_last_offset(NULL, ip, &last_block,                          xfs_bmap_last_offset(NULL, ip, &last_block,
                                 XFS_DATA_FORK);                                  XFS_DATA_FORK);
Line 788  xfs_iomap_write_allocate( Line 816  xfs_iomap_write_allocate(
                         /* Go get the actual blocks */                          /* Go get the actual blocks */
                         error = xfs_bmapi(tp, ip, map_start_fsb, count_fsb,                          error = xfs_bmapi(tp, ip, map_start_fsb, count_fsb,
                                         XFS_BMAPI_WRITE, &first_block, 1,                                          XFS_BMAPI_WRITE, &first_block, 1,
                                         imap, &nimaps, &free_list, NULL);                                          &imap, &nimaps, &free_list, NULL);
                         if (error)                          if (error)
                                 goto trans_cancel;                                  goto trans_cancel;
   
Line 807  xfs_iomap_write_allocate( Line 835  xfs_iomap_write_allocate(
                  * See if we were able to allocate an extent that                   * See if we were able to allocate an extent that
                  * covers at least part of the callers request                   * covers at least part of the callers request
                  */                   */
                 for (i = 0; i < nimaps; i++) {                  if (unlikely(!imap.br_startblock &&
                         if (unlikely(!imap[i].br_startblock &&                               XFS_IS_REALTIME_INODE(ip)))
                                      !(ip->i_d.di_flags & XFS_DIFLAG_REALTIME)))                          return xfs_cmn_err_fsblock_zero(ip, &imap);
                                 return xfs_cmn_err_fsblock_zero(ip, &imap[i]);                  if ((offset_fsb >= imap.br_startoff) &&
                         if ((offset_fsb >= imap[i].br_startoff) &&                      (offset_fsb < (imap.br_startoff +
                             (offset_fsb < (imap[i].br_startoff +                                     imap.br_blockcount))) {
                                            imap[i].br_blockcount))) {                          *map = imap;
                                 *map = imap[i];                          *retmap = 1;
                                 *retmap = 1;                          XFS_STATS_INC(xs_xstrat_quick);
                                 XFS_STATS_INC(xs_xstrat_quick);                          return 0;
                                 return 0;  
                         }  
                         count_fsb -= imap[i].br_blockcount;  
                 }                  }
   
                 /* So far we have not mapped the requested part of the                  /*
                    * So far we have not mapped the requested part of the
                  * file, just surrounding data, try again.                   * file, just surrounding data, try again.
                  */                   */
                 nimaps--;                  count_fsb -= imap.br_blockcount;
                 map_start_fsb = imap[nimaps].br_startoff +                  map_start_fsb = imap.br_startoff + imap.br_blockcount;
                                 imap[nimaps].br_blockcount;  
         }          }
   
 trans_cancel:  trans_cancel:

Removed from v.1.59  
changed lines
  Added in v.1.60


FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>