mp = args->dp->i_mount;
 
        /*
-        * Roll through the "value", invalidating the attribute value's
-        * blocks.
+        * Roll through the "value", invalidating the attribute value's blocks.
+        * Note that args->rmtblkcnt is the minimum number of data blocks we'll
+        * see for a CRC enabled remote attribute. Each extent will have a
+        * header, and so we may have more blocks than we realise here.  If we
+        * fail to map the blocks correctly, we'll have problems with the buffer
+        * lookups.
         */
        lblkno = args->rmtblkno;
-       valuelen = args->rmtblkcnt;
+       valuelen = args->valuelen;
+       blkcnt = xfs_attr3_rmt_blocks(mp, valuelen);
        while (valuelen > 0) {
+               int dblkcnt;
+
                /*
                 * Try to remember where we decided to put the value.
                 */
                nmap = 1;
                error = xfs_bmapi_read(args->dp, (xfs_fileoff_t)lblkno,
-                                      args->rmtblkcnt, &map, &nmap,
-                                      XFS_BMAPI_ATTRFORK);
+                                      blkcnt, &map, &nmap, XFS_BMAPI_ATTRFORK);
                if (error)
                        return(error);
                ASSERT(nmap == 1);
                       (map.br_startblock != HOLESTARTBLOCK));
 
                dblkno = XFS_FSB_TO_DADDR(mp, map.br_startblock),
-               blkcnt = XFS_FSB_TO_BB(mp, map.br_blockcount);
+               dblkcnt = XFS_FSB_TO_BB(mp, map.br_blockcount);
 
                /*
                 * If the "remote" value is in the cache, remove it.
                 */
-               bp = xfs_incore(mp->m_ddev_targp, dblkno, blkcnt, XBF_TRYLOCK);
+               bp = xfs_incore(mp->m_ddev_targp, dblkno, dblkcnt, XBF_TRYLOCK);
                if (bp) {
                        xfs_buf_stale(bp);
                        xfs_buf_relse(bp);
                        bp = NULL;
                }
 
-               valuelen -= map.br_blockcount;
+               valuelen -= XFS_ATTR3_RMT_BUF_SPACE(mp,
+                                       XFS_FSB_TO_B(mp, map.br_blockcount));
 
                lblkno += map.br_blockcount;
+               blkcnt -= map.br_blockcount;
+               blkcnt = max(blkcnt, xfs_attr3_rmt_blocks(mp, valuelen));
        }
 
        /*
         * Keep de-allocating extents until the remote-value region is gone.
         */
+       blkcnt = lblkno - args->rmtblkno;
        lblkno = args->rmtblkno;
-       blkcnt = args->rmtblkcnt;
        done = 0;
        while (!done) {
                xfs_bmap_init(args->flist, args->firstblock);