~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/fs/xfs/libxfs/xfs_rmap.c

Version: ~ [ linux-5.13-rc5 ] ~ [ linux-5.12.9 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.42 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.124 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.193 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.235 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.271 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.271 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.18.140 ] ~ [ linux-3.16.85 ] ~ [ linux-3.14.79 ] ~ [ linux-3.12.74 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /*
  2  * Copyright (c) 2014 Red Hat, Inc.
  3  * All Rights Reserved.
  4  *
  5  * This program is free software; you can redistribute it and/or
  6  * modify it under the terms of the GNU General Public License as
  7  * published by the Free Software Foundation.
  8  *
  9  * This program is distributed in the hope that it would be useful,
 10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 12  * GNU General Public License for more details.
 13  *
 14  * You should have received a copy of the GNU General Public License
 15  * along with this program; if not, write the Free Software Foundation,
 16  * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 17  */
 18 #include "xfs.h"
 19 #include "xfs_fs.h"
 20 #include "xfs_shared.h"
 21 #include "xfs_format.h"
 22 #include "xfs_log_format.h"
 23 #include "xfs_trans_resv.h"
 24 #include "xfs_bit.h"
 25 #include "xfs_sb.h"
 26 #include "xfs_mount.h"
 27 #include "xfs_defer.h"
 28 #include "xfs_da_format.h"
 29 #include "xfs_da_btree.h"
 30 #include "xfs_btree.h"
 31 #include "xfs_trans.h"
 32 #include "xfs_alloc.h"
 33 #include "xfs_rmap.h"
 34 #include "xfs_rmap_btree.h"
 35 #include "xfs_trans_space.h"
 36 #include "xfs_trace.h"
 37 #include "xfs_errortag.h"
 38 #include "xfs_error.h"
 39 #include "xfs_extent_busy.h"
 40 #include "xfs_bmap.h"
 41 #include "xfs_inode.h"
 42 
 43 /*
 44  * Lookup the first record less than or equal to [bno, len, owner, offset]
 45  * in the btree given by cur.
 46  */
 47 int
 48 xfs_rmap_lookup_le(
 49         struct xfs_btree_cur    *cur,
 50         xfs_agblock_t           bno,
 51         xfs_extlen_t            len,
 52         uint64_t                owner,
 53         uint64_t                offset,
 54         unsigned int            flags,
 55         int                     *stat)
 56 {
 57         cur->bc_rec.r.rm_startblock = bno;
 58         cur->bc_rec.r.rm_blockcount = len;
 59         cur->bc_rec.r.rm_owner = owner;
 60         cur->bc_rec.r.rm_offset = offset;
 61         cur->bc_rec.r.rm_flags = flags;
 62         return xfs_btree_lookup(cur, XFS_LOOKUP_LE, stat);
 63 }
 64 
 65 /*
 66  * Lookup the record exactly matching [bno, len, owner, offset]
 67  * in the btree given by cur.
 68  */
 69 int
 70 xfs_rmap_lookup_eq(
 71         struct xfs_btree_cur    *cur,
 72         xfs_agblock_t           bno,
 73         xfs_extlen_t            len,
 74         uint64_t                owner,
 75         uint64_t                offset,
 76         unsigned int            flags,
 77         int                     *stat)
 78 {
 79         cur->bc_rec.r.rm_startblock = bno;
 80         cur->bc_rec.r.rm_blockcount = len;
 81         cur->bc_rec.r.rm_owner = owner;
 82         cur->bc_rec.r.rm_offset = offset;
 83         cur->bc_rec.r.rm_flags = flags;
 84         return xfs_btree_lookup(cur, XFS_LOOKUP_EQ, stat);
 85 }
 86 
 87 /*
 88  * Update the record referred to by cur to the value given
 89  * by [bno, len, owner, offset].
 90  * This either works (return 0) or gets an EFSCORRUPTED error.
 91  */
 92 STATIC int
 93 xfs_rmap_update(
 94         struct xfs_btree_cur    *cur,
 95         struct xfs_rmap_irec    *irec)
 96 {
 97         union xfs_btree_rec     rec;
 98         int                     error;
 99 
100         trace_xfs_rmap_update(cur->bc_mp, cur->bc_private.a.agno,
101                         irec->rm_startblock, irec->rm_blockcount,
102                         irec->rm_owner, irec->rm_offset, irec->rm_flags);
103 
104         rec.rmap.rm_startblock = cpu_to_be32(irec->rm_startblock);
105         rec.rmap.rm_blockcount = cpu_to_be32(irec->rm_blockcount);
106         rec.rmap.rm_owner = cpu_to_be64(irec->rm_owner);
107         rec.rmap.rm_offset = cpu_to_be64(
108                         xfs_rmap_irec_offset_pack(irec));
109         error = xfs_btree_update(cur, &rec);
110         if (error)
111                 trace_xfs_rmap_update_error(cur->bc_mp,
112                                 cur->bc_private.a.agno, error, _RET_IP_);
113         return error;
114 }
115 
116 int
117 xfs_rmap_insert(
118         struct xfs_btree_cur    *rcur,
119         xfs_agblock_t           agbno,
120         xfs_extlen_t            len,
121         uint64_t                owner,
122         uint64_t                offset,
123         unsigned int            flags)
124 {
125         int                     i;
126         int                     error;
127 
128         trace_xfs_rmap_insert(rcur->bc_mp, rcur->bc_private.a.agno, agbno,
129                         len, owner, offset, flags);
130 
131         error = xfs_rmap_lookup_eq(rcur, agbno, len, owner, offset, flags, &i);
132         if (error)
133                 goto done;
134         XFS_WANT_CORRUPTED_GOTO(rcur->bc_mp, i == 0, done);
135 
136         rcur->bc_rec.r.rm_startblock = agbno;
137         rcur->bc_rec.r.rm_blockcount = len;
138         rcur->bc_rec.r.rm_owner = owner;
139         rcur->bc_rec.r.rm_offset = offset;
140         rcur->bc_rec.r.rm_flags = flags;
141         error = xfs_btree_insert(rcur, &i);
142         if (error)
143                 goto done;
144         XFS_WANT_CORRUPTED_GOTO(rcur->bc_mp, i == 1, done);
145 done:
146         if (error)
147                 trace_xfs_rmap_insert_error(rcur->bc_mp,
148                                 rcur->bc_private.a.agno, error, _RET_IP_);
149         return error;
150 }
151 
152 STATIC int
153 xfs_rmap_delete(
154         struct xfs_btree_cur    *rcur,
155         xfs_agblock_t           agbno,
156         xfs_extlen_t            len,
157         uint64_t                owner,
158         uint64_t                offset,
159         unsigned int            flags)
160 {
161         int                     i;
162         int                     error;
163 
164         trace_xfs_rmap_delete(rcur->bc_mp, rcur->bc_private.a.agno, agbno,
165                         len, owner, offset, flags);
166 
167         error = xfs_rmap_lookup_eq(rcur, agbno, len, owner, offset, flags, &i);
168         if (error)
169                 goto done;
170         XFS_WANT_CORRUPTED_GOTO(rcur->bc_mp, i == 1, done);
171 
172         error = xfs_btree_delete(rcur, &i);
173         if (error)
174                 goto done;
175         XFS_WANT_CORRUPTED_GOTO(rcur->bc_mp, i == 1, done);
176 done:
177         if (error)
178                 trace_xfs_rmap_delete_error(rcur->bc_mp,
179                                 rcur->bc_private.a.agno, error, _RET_IP_);
180         return error;
181 }
182 
183 /* Convert an internal btree record to an rmap record. */
184 int
185 xfs_rmap_btrec_to_irec(
186         union xfs_btree_rec     *rec,
187         struct xfs_rmap_irec    *irec)
188 {
189         irec->rm_flags = 0;
190         irec->rm_startblock = be32_to_cpu(rec->rmap.rm_startblock);
191         irec->rm_blockcount = be32_to_cpu(rec->rmap.rm_blockcount);
192         irec->rm_owner = be64_to_cpu(rec->rmap.rm_owner);
193         return xfs_rmap_irec_offset_unpack(be64_to_cpu(rec->rmap.rm_offset),
194                         irec);
195 }
196 
197 /*
198  * Get the data from the pointed-to record.
199  */
200 int
201 xfs_rmap_get_rec(
202         struct xfs_btree_cur    *cur,
203         struct xfs_rmap_irec    *irec,
204         int                     *stat)
205 {
206         union xfs_btree_rec     *rec;
207         int                     error;
208 
209         error = xfs_btree_get_rec(cur, &rec, stat);
210         if (error || !*stat)
211                 return error;
212 
213         return xfs_rmap_btrec_to_irec(rec, irec);
214 }
215 
216 struct xfs_find_left_neighbor_info {
217         struct xfs_rmap_irec    high;
218         struct xfs_rmap_irec    *irec;
219         int                     *stat;
220 };
221 
222 /* For each rmap given, figure out if it matches the key we want. */
223 STATIC int
224 xfs_rmap_find_left_neighbor_helper(
225         struct xfs_btree_cur    *cur,
226         struct xfs_rmap_irec    *rec,
227         void                    *priv)
228 {
229         struct xfs_find_left_neighbor_info      *info = priv;
230 
231         trace_xfs_rmap_find_left_neighbor_candidate(cur->bc_mp,
232                         cur->bc_private.a.agno, rec->rm_startblock,
233                         rec->rm_blockcount, rec->rm_owner, rec->rm_offset,
234                         rec->rm_flags);
235 
236         if (rec->rm_owner != info->high.rm_owner)
237                 return XFS_BTREE_QUERY_RANGE_CONTINUE;
238         if (!XFS_RMAP_NON_INODE_OWNER(rec->rm_owner) &&
239             !(rec->rm_flags & XFS_RMAP_BMBT_BLOCK) &&
240             rec->rm_offset + rec->rm_blockcount - 1 != info->high.rm_offset)
241                 return XFS_BTREE_QUERY_RANGE_CONTINUE;
242 
243         *info->irec = *rec;
244         *info->stat = 1;
245         return XFS_BTREE_QUERY_RANGE_ABORT;
246 }
247 
248 /*
249  * Find the record to the left of the given extent, being careful only to
250  * return a match with the same owner and adjacent physical and logical
251  * block ranges.
252  */
253 int
254 xfs_rmap_find_left_neighbor(
255         struct xfs_btree_cur    *cur,
256         xfs_agblock_t           bno,
257         uint64_t                owner,
258         uint64_t                offset,
259         unsigned int            flags,
260         struct xfs_rmap_irec    *irec,
261         int                     *stat)
262 {
263         struct xfs_find_left_neighbor_info      info;
264         int                     error;
265 
266         *stat = 0;
267         if (bno == 0)
268                 return 0;
269         info.high.rm_startblock = bno - 1;
270         info.high.rm_owner = owner;
271         if (!XFS_RMAP_NON_INODE_OWNER(owner) &&
272             !(flags & XFS_RMAP_BMBT_BLOCK)) {
273                 if (offset == 0)
274                         return 0;
275                 info.high.rm_offset = offset - 1;
276         } else
277                 info.high.rm_offset = 0;
278         info.high.rm_flags = flags;
279         info.high.rm_blockcount = 0;
280         info.irec = irec;
281         info.stat = stat;
282 
283         trace_xfs_rmap_find_left_neighbor_query(cur->bc_mp,
284                         cur->bc_private.a.agno, bno, 0, owner, offset, flags);
285 
286         error = xfs_rmap_query_range(cur, &info.high, &info.high,
287                         xfs_rmap_find_left_neighbor_helper, &info);
288         if (error == XFS_BTREE_QUERY_RANGE_ABORT)
289                 error = 0;
290         if (*stat)
291                 trace_xfs_rmap_find_left_neighbor_result(cur->bc_mp,
292                                 cur->bc_private.a.agno, irec->rm_startblock,
293                                 irec->rm_blockcount, irec->rm_owner,
294                                 irec->rm_offset, irec->rm_flags);
295         return error;
296 }
297 
298 /* For each rmap given, figure out if it matches the key we want. */
299 STATIC int
300 xfs_rmap_lookup_le_range_helper(
301         struct xfs_btree_cur    *cur,
302         struct xfs_rmap_irec    *rec,
303         void                    *priv)
304 {
305         struct xfs_find_left_neighbor_info      *info = priv;
306 
307         trace_xfs_rmap_lookup_le_range_candidate(cur->bc_mp,
308                         cur->bc_private.a.agno, rec->rm_startblock,
309                         rec->rm_blockcount, rec->rm_owner, rec->rm_offset,
310                         rec->rm_flags);
311 
312         if (rec->rm_owner != info->high.rm_owner)
313                 return XFS_BTREE_QUERY_RANGE_CONTINUE;
314         if (!XFS_RMAP_NON_INODE_OWNER(rec->rm_owner) &&
315             !(rec->rm_flags & XFS_RMAP_BMBT_BLOCK) &&
316             (rec->rm_offset > info->high.rm_offset ||
317              rec->rm_offset + rec->rm_blockcount <= info->high.rm_offset))
318                 return XFS_BTREE_QUERY_RANGE_CONTINUE;
319 
320         *info->irec = *rec;
321         *info->stat = 1;
322         return XFS_BTREE_QUERY_RANGE_ABORT;
323 }
324 
325 /*
326  * Find the record to the left of the given extent, being careful only to
327  * return a match with the same owner and overlapping physical and logical
328  * block ranges.  This is the overlapping-interval version of
329  * xfs_rmap_lookup_le.
330  */
331 int
332 xfs_rmap_lookup_le_range(
333         struct xfs_btree_cur    *cur,
334         xfs_agblock_t           bno,
335         uint64_t                owner,
336         uint64_t                offset,
337         unsigned int            flags,
338         struct xfs_rmap_irec    *irec,
339         int                     *stat)
340 {
341         struct xfs_find_left_neighbor_info      info;
342         int                     error;
343 
344         info.high.rm_startblock = bno;
345         info.high.rm_owner = owner;
346         if (!XFS_RMAP_NON_INODE_OWNER(owner) && !(flags & XFS_RMAP_BMBT_BLOCK))
347                 info.high.rm_offset = offset;
348         else
349                 info.high.rm_offset = 0;
350         info.high.rm_flags = flags;
351         info.high.rm_blockcount = 0;
352         *stat = 0;
353         info.irec = irec;
354         info.stat = stat;
355 
356         trace_xfs_rmap_lookup_le_range(cur->bc_mp,
357                         cur->bc_private.a.agno, bno, 0, owner, offset, flags);
358         error = xfs_rmap_query_range(cur, &info.high, &info.high,
359                         xfs_rmap_lookup_le_range_helper, &info);
360         if (error == XFS_BTREE_QUERY_RANGE_ABORT)
361                 error = 0;
362         if (*stat)
363                 trace_xfs_rmap_lookup_le_range_result(cur->bc_mp,
364                                 cur->bc_private.a.agno, irec->rm_startblock,
365                                 irec->rm_blockcount, irec->rm_owner,
366                                 irec->rm_offset, irec->rm_flags);
367         return error;
368 }
369 
370 /*
371  * Perform all the relevant owner checks for a removal op.  If we're doing an
372  * unknown-owner removal then we have no owner information to check.
373  */
374 static int
375 xfs_rmap_free_check_owner(
376         struct xfs_mount        *mp,
377         uint64_t                ltoff,
378         struct xfs_rmap_irec    *rec,
379         xfs_fsblock_t           bno,
380         xfs_filblks_t           len,
381         uint64_t                owner,
382         uint64_t                offset,
383         unsigned int            flags)
384 {
385         int                     error = 0;
386 
387         if (owner == XFS_RMAP_OWN_UNKNOWN)
388                 return 0;
389 
390         /* Make sure the unwritten flag matches. */
391         XFS_WANT_CORRUPTED_GOTO(mp, (flags & XFS_RMAP_UNWRITTEN) ==
392                         (rec->rm_flags & XFS_RMAP_UNWRITTEN), out);
393 
394         /* Make sure the owner matches what we expect to find in the tree. */
395         XFS_WANT_CORRUPTED_GOTO(mp, owner == rec->rm_owner, out);
396 
397         /* Check the offset, if necessary. */
398         if (XFS_RMAP_NON_INODE_OWNER(owner))
399                 goto out;
400 
401         if (flags & XFS_RMAP_BMBT_BLOCK) {
402                 XFS_WANT_CORRUPTED_GOTO(mp, rec->rm_flags & XFS_RMAP_BMBT_BLOCK,
403                                 out);
404         } else {
405                 XFS_WANT_CORRUPTED_GOTO(mp, rec->rm_offset <= offset, out);
406                 XFS_WANT_CORRUPTED_GOTO(mp,
407                                 ltoff + rec->rm_blockcount >= offset + len,
408                                 out);
409         }
410 
411 out:
412         return error;
413 }
414 
415 /*
416  * Find the extent in the rmap btree and remove it.
417  *
418  * The record we find should always be an exact match for the extent that we're
419  * looking for, since we insert them into the btree without modification.
420  *
421  * Special Case #1: when growing the filesystem, we "free" an extent when
422  * growing the last AG. This extent is new space and so it is not tracked as
423  * used space in the btree. The growfs code will pass in an owner of
424  * XFS_RMAP_OWN_NULL to indicate that it expected that there is no owner of this
425  * extent. We verify that - the extent lookup result in a record that does not
426  * overlap.
427  *
428  * Special Case #2: EFIs do not record the owner of the extent, so when
429  * recovering EFIs from the log we pass in XFS_RMAP_OWN_UNKNOWN to tell the rmap
430  * btree to ignore the owner (i.e. wildcard match) so we don't trigger
431  * corruption checks during log recovery.
432  */
433 STATIC int
434 xfs_rmap_unmap(
435         struct xfs_btree_cur    *cur,
436         xfs_agblock_t           bno,
437         xfs_extlen_t            len,
438         bool                    unwritten,
439         struct xfs_owner_info   *oinfo)
440 {
441         struct xfs_mount        *mp = cur->bc_mp;
442         struct xfs_rmap_irec    ltrec;
443         uint64_t                ltoff;
444         int                     error = 0;
445         int                     i;
446         uint64_t                owner;
447         uint64_t                offset;
448         unsigned int            flags;
449         bool                    ignore_off;
450 
451         xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
452         ignore_off = XFS_RMAP_NON_INODE_OWNER(owner) ||
453                         (flags & XFS_RMAP_BMBT_BLOCK);
454         if (unwritten)
455                 flags |= XFS_RMAP_UNWRITTEN;
456         trace_xfs_rmap_unmap(mp, cur->bc_private.a.agno, bno, len,
457                         unwritten, oinfo);
458 
459         /*
460          * We should always have a left record because there's a static record
461          * for the AG headers at rm_startblock == 0 created by mkfs/growfs that
462          * will not ever be removed from the tree.
463          */
464         error = xfs_rmap_lookup_le(cur, bno, len, owner, offset, flags, &i);
465         if (error)
466                 goto out_error;
467         XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error);
468 
469         error = xfs_rmap_get_rec(cur, &ltrec, &i);
470         if (error)
471                 goto out_error;
472         XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error);
473         trace_xfs_rmap_lookup_le_range_result(cur->bc_mp,
474                         cur->bc_private.a.agno, ltrec.rm_startblock,
475                         ltrec.rm_blockcount, ltrec.rm_owner,
476                         ltrec.rm_offset, ltrec.rm_flags);
477         ltoff = ltrec.rm_offset;
478 
479         /*
480          * For growfs, the incoming extent must be beyond the left record we
481          * just found as it is new space and won't be used by anyone. This is
482          * just a corruption check as we don't actually do anything with this
483          * extent.  Note that we need to use >= instead of > because it might
484          * be the case that the "left" extent goes all the way to EOFS.
485          */
486         if (owner == XFS_RMAP_OWN_NULL) {
487                 XFS_WANT_CORRUPTED_GOTO(mp, bno >= ltrec.rm_startblock +
488                                                 ltrec.rm_blockcount, out_error);
489                 goto out_done;
490         }
491 
492         /*
493          * If we're doing an unknown-owner removal for EFI recovery, we expect
494          * to find the full range in the rmapbt or nothing at all.  If we
495          * don't find any rmaps overlapping either end of the range, we're
496          * done.  Hopefully this means that the EFI creator already queued
497          * (and finished) a RUI to remove the rmap.
498          */
499         if (owner == XFS_RMAP_OWN_UNKNOWN &&
500             ltrec.rm_startblock + ltrec.rm_blockcount <= bno) {
501                 struct xfs_rmap_irec    rtrec;
502 
503                 error = xfs_btree_increment(cur, 0, &i);
504                 if (error)
505                         goto out_error;
506                 if (i == 0)
507                         goto out_done;
508                 error = xfs_rmap_get_rec(cur, &rtrec, &i);
509                 if (error)
510                         goto out_error;
511                 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error);
512                 if (rtrec.rm_startblock >= bno + len)
513                         goto out_done;
514         }
515 
516         /* Make sure the extent we found covers the entire freeing range. */
517         XFS_WANT_CORRUPTED_GOTO(mp, ltrec.rm_startblock <= bno &&
518                         ltrec.rm_startblock + ltrec.rm_blockcount >=
519                         bno + len, out_error);
520 
521         /* Check owner information. */
522         error = xfs_rmap_free_check_owner(mp, ltoff, &ltrec, bno, len, owner,
523                         offset, flags);
524         if (error)
525                 goto out_error;
526 
527         if (ltrec.rm_startblock == bno && ltrec.rm_blockcount == len) {
528                 /* exact match, simply remove the record from rmap tree */
529                 trace_xfs_rmap_delete(mp, cur->bc_private.a.agno,
530                                 ltrec.rm_startblock, ltrec.rm_blockcount,
531                                 ltrec.rm_owner, ltrec.rm_offset,
532                                 ltrec.rm_flags);
533                 error = xfs_btree_delete(cur, &i);
534                 if (error)
535                         goto out_error;
536                 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error);
537         } else if (ltrec.rm_startblock == bno) {
538                 /*
539                  * overlap left hand side of extent: move the start, trim the
540                  * length and update the current record.
541                  *
542                  *       ltbno                ltlen
543                  * Orig:    |oooooooooooooooooooo|
544                  * Freeing: |fffffffff|
545                  * Result:            |rrrrrrrrrr|
546                  *         bno       len
547                  */
548                 ltrec.rm_startblock += len;
549                 ltrec.rm_blockcount -= len;
550                 if (!ignore_off)
551                         ltrec.rm_offset += len;
552                 error = xfs_rmap_update(cur, &ltrec);
553                 if (error)
554                         goto out_error;
555         } else if (ltrec.rm_startblock + ltrec.rm_blockcount == bno + len) {
556                 /*
557                  * overlap right hand side of extent: trim the length and update
558                  * the current record.
559                  *
560                  *       ltbno                ltlen
561                  * Orig:    |oooooooooooooooooooo|
562                  * Freeing:            |fffffffff|
563                  * Result:  |rrrrrrrrrr|
564                  *                    bno       len
565                  */
566                 ltrec.rm_blockcount -= len;
567                 error = xfs_rmap_update(cur, &ltrec);
568                 if (error)
569                         goto out_error;
570         } else {
571 
572                 /*
573                  * overlap middle of extent: trim the length of the existing
574                  * record to the length of the new left-extent size, increment
575                  * the insertion position so we can insert a new record
576                  * containing the remaining right-extent space.
577                  *
578                  *       ltbno                ltlen
579                  * Orig:    |oooooooooooooooooooo|
580                  * Freeing:       |fffffffff|
581                  * Result:  |rrrrr|         |rrrr|
582                  *               bno       len
583                  */
584                 xfs_extlen_t    orig_len = ltrec.rm_blockcount;
585 
586                 ltrec.rm_blockcount = bno - ltrec.rm_startblock;
587                 error = xfs_rmap_update(cur, &ltrec);
588                 if (error)
589                         goto out_error;
590 
591                 error = xfs_btree_increment(cur, 0, &i);
592                 if (error)
593                         goto out_error;
594 
595                 cur->bc_rec.r.rm_startblock = bno + len;
596                 cur->bc_rec.r.rm_blockcount = orig_len - len -
597                                                      ltrec.rm_blockcount;
598                 cur->bc_rec.r.rm_owner = ltrec.rm_owner;
599                 if (ignore_off)
600                         cur->bc_rec.r.rm_offset = 0;
601                 else
602                         cur->bc_rec.r.rm_offset = offset + len;
603                 cur->bc_rec.r.rm_flags = flags;
604                 trace_xfs_rmap_insert(mp, cur->bc_private.a.agno,
605                                 cur->bc_rec.r.rm_startblock,
606                                 cur->bc_rec.r.rm_blockcount,
607                                 cur->bc_rec.r.rm_owner,
608                                 cur->bc_rec.r.rm_offset,
609                                 cur->bc_rec.r.rm_flags);
610                 error = xfs_btree_insert(cur, &i);
611                 if (error)
612                         goto out_error;
613         }
614 
615 out_done:
616         trace_xfs_rmap_unmap_done(mp, cur->bc_private.a.agno, bno, len,
617                         unwritten, oinfo);
618 out_error:
619         if (error)
620                 trace_xfs_rmap_unmap_error(mp, cur->bc_private.a.agno,
621                                 error, _RET_IP_);
622         return error;
623 }
624 
625 /*
626  * Remove a reference to an extent in the rmap btree.
627  */
628 int
629 xfs_rmap_free(
630         struct xfs_trans        *tp,
631         struct xfs_buf          *agbp,
632         xfs_agnumber_t          agno,
633         xfs_agblock_t           bno,
634         xfs_extlen_t            len,
635         struct xfs_owner_info   *oinfo)
636 {
637         struct xfs_mount        *mp = tp->t_mountp;
638         struct xfs_btree_cur    *cur;
639         int                     error;
640 
641         if (!xfs_sb_version_hasrmapbt(&mp->m_sb))
642                 return 0;
643 
644         cur = xfs_rmapbt_init_cursor(mp, tp, agbp, agno);
645 
646         error = xfs_rmap_unmap(cur, bno, len, false, oinfo);
647         if (error)
648                 goto out_error;
649 
650         xfs_btree_del_cursor(cur, XFS_BTREE_NOERROR);
651         return 0;
652 
653 out_error:
654         xfs_btree_del_cursor(cur, XFS_BTREE_ERROR);
655         return error;
656 }
657 
658 /*
659  * A mergeable rmap must have the same owner and the same values for
660  * the unwritten, attr_fork, and bmbt flags.  The startblock and
661  * offset are checked separately.
662  */
663 static bool
664 xfs_rmap_is_mergeable(
665         struct xfs_rmap_irec    *irec,
666         uint64_t                owner,
667         unsigned int            flags)
668 {
669         if (irec->rm_owner == XFS_RMAP_OWN_NULL)
670                 return false;
671         if (irec->rm_owner != owner)
672                 return false;
673         if ((flags & XFS_RMAP_UNWRITTEN) ^
674             (irec->rm_flags & XFS_RMAP_UNWRITTEN))
675                 return false;
676         if ((flags & XFS_RMAP_ATTR_FORK) ^
677             (irec->rm_flags & XFS_RMAP_ATTR_FORK))
678                 return false;
679         if ((flags & XFS_RMAP_BMBT_BLOCK) ^
680             (irec->rm_flags & XFS_RMAP_BMBT_BLOCK))
681                 return false;
682         return true;
683 }
684 
685 /*
686  * When we allocate a new block, the first thing we do is add a reference to
687  * the extent in the rmap btree. This takes the form of a [agbno, length,
688  * owner, offset] record.  Flags are encoded in the high bits of the offset
689  * field.
690  */
691 STATIC int
692 xfs_rmap_map(
693         struct xfs_btree_cur    *cur,
694         xfs_agblock_t           bno,
695         xfs_extlen_t            len,
696         bool                    unwritten,
697         struct xfs_owner_info   *oinfo)
698 {
699         struct xfs_mount        *mp = cur->bc_mp;
700         struct xfs_rmap_irec    ltrec;
701         struct xfs_rmap_irec    gtrec;
702         int                     have_gt;
703         int                     have_lt;
704         int                     error = 0;
705         int                     i;
706         uint64_t                owner;
707         uint64_t                offset;
708         unsigned int            flags = 0;
709         bool                    ignore_off;
710 
711         xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
712         ASSERT(owner != 0);
713         ignore_off = XFS_RMAP_NON_INODE_OWNER(owner) ||
714                         (flags & XFS_RMAP_BMBT_BLOCK);
715         if (unwritten)
716                 flags |= XFS_RMAP_UNWRITTEN;
717         trace_xfs_rmap_map(mp, cur->bc_private.a.agno, bno, len,
718                         unwritten, oinfo);
719         ASSERT(!xfs_rmap_should_skip_owner_update(oinfo));
720 
721         /*
722          * For the initial lookup, look for an exact match or the left-adjacent
723          * record for our insertion point. This will also give us the record for
724          * start block contiguity tests.
725          */
726         error = xfs_rmap_lookup_le(cur, bno, len, owner, offset, flags,
727                         &have_lt);
728         if (error)
729                 goto out_error;
730         XFS_WANT_CORRUPTED_GOTO(mp, have_lt == 1, out_error);
731 
732         error = xfs_rmap_get_rec(cur, &ltrec, &have_lt);
733         if (error)
734                 goto out_error;
735         XFS_WANT_CORRUPTED_GOTO(mp, have_lt == 1, out_error);
736         trace_xfs_rmap_lookup_le_range_result(cur->bc_mp,
737                         cur->bc_private.a.agno, ltrec.rm_startblock,
738                         ltrec.rm_blockcount, ltrec.rm_owner,
739                         ltrec.rm_offset, ltrec.rm_flags);
740 
741         if (!xfs_rmap_is_mergeable(&ltrec, owner, flags))
742                 have_lt = 0;
743 
744         XFS_WANT_CORRUPTED_GOTO(mp,
745                 have_lt == 0 ||
746                 ltrec.rm_startblock + ltrec.rm_blockcount <= bno, out_error);
747 
748         /*
749          * Increment the cursor to see if we have a right-adjacent record to our
750          * insertion point. This will give us the record for end block
751          * contiguity tests.
752          */
753         error = xfs_btree_increment(cur, 0, &have_gt);
754         if (error)
755                 goto out_error;
756         if (have_gt) {
757                 error = xfs_rmap_get_rec(cur, &gtrec, &have_gt);
758                 if (error)
759                         goto out_error;
760                 XFS_WANT_CORRUPTED_GOTO(mp, have_gt == 1, out_error);
761                 XFS_WANT_CORRUPTED_GOTO(mp, bno + len <= gtrec.rm_startblock,
762                                         out_error);
763                 trace_xfs_rmap_find_right_neighbor_result(cur->bc_mp,
764                         cur->bc_private.a.agno, gtrec.rm_startblock,
765                         gtrec.rm_blockcount, gtrec.rm_owner,
766                         gtrec.rm_offset, gtrec.rm_flags);
767                 if (!xfs_rmap_is_mergeable(&gtrec, owner, flags))
768                         have_gt = 0;
769         }
770 
771         /*
772          * Note: cursor currently points one record to the right of ltrec, even
773          * if there is no record in the tree to the right.
774          */
775         if (have_lt &&
776             ltrec.rm_startblock + ltrec.rm_blockcount == bno &&
777             (ignore_off || ltrec.rm_offset + ltrec.rm_blockcount == offset)) {
778                 /*
779                  * left edge contiguous, merge into left record.
780                  *
781                  *       ltbno     ltlen
782                  * orig:   |ooooooooo|
783                  * adding:           |aaaaaaaaa|
784                  * result: |rrrrrrrrrrrrrrrrrrr|
785                  *                  bno       len
786                  */
787                 ltrec.rm_blockcount += len;
788                 if (have_gt &&
789                     bno + len == gtrec.rm_startblock &&
790                     (ignore_off || offset + len == gtrec.rm_offset) &&
791                     (unsigned long)ltrec.rm_blockcount + len +
792                                 gtrec.rm_blockcount <= XFS_RMAP_LEN_MAX) {
793                         /*
794                          * right edge also contiguous, delete right record
795                          * and merge into left record.
796                          *
797                          *       ltbno     ltlen    gtbno     gtlen
798                          * orig:   |ooooooooo|         |ooooooooo|
799                          * adding:           |aaaaaaaaa|
800                          * result: |rrrrrrrrrrrrrrrrrrrrrrrrrrrrr|
801                          */
802                         ltrec.rm_blockcount += gtrec.rm_blockcount;
803                         trace_xfs_rmap_delete(mp, cur->bc_private.a.agno,
804                                         gtrec.rm_startblock,
805                                         gtrec.rm_blockcount,
806                                         gtrec.rm_owner,
807                                         gtrec.rm_offset,
808                                         gtrec.rm_flags);
809                         error = xfs_btree_delete(cur, &i);
810                         if (error)
811                                 goto out_error;
812                         XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error);
813                 }
814 
815                 /* point the cursor back to the left record and update */
816                 error = xfs_btree_decrement(cur, 0, &have_gt);
817                 if (error)
818                         goto out_error;
819                 error = xfs_rmap_update(cur, &ltrec);
820                 if (error)
821                         goto out_error;
822         } else if (have_gt &&
823                    bno + len == gtrec.rm_startblock &&
824                    (ignore_off || offset + len == gtrec.rm_offset)) {
825                 /*
826                  * right edge contiguous, merge into right record.
827                  *
828                  *                 gtbno     gtlen
829                  * Orig:             |ooooooooo|
830                  * adding: |aaaaaaaaa|
831                  * Result: |rrrrrrrrrrrrrrrrrrr|
832                  *        bno       len
833                  */
834                 gtrec.rm_startblock = bno;
835                 gtrec.rm_blockcount += len;
836                 if (!ignore_off)
837                         gtrec.rm_offset = offset;
838                 error = xfs_rmap_update(cur, &gtrec);
839                 if (error)
840                         goto out_error;
841         } else {
842                 /*
843                  * no contiguous edge with identical owner, insert
844                  * new record at current cursor position.
845                  */
846                 cur->bc_rec.r.rm_startblock = bno;
847                 cur->bc_rec.r.rm_blockcount = len;
848                 cur->bc_rec.r.rm_owner = owner;
849                 cur->bc_rec.r.rm_offset = offset;
850                 cur->bc_rec.r.rm_flags = flags;
851                 trace_xfs_rmap_insert(mp, cur->bc_private.a.agno, bno, len,
852                         owner, offset, flags);
853                 error = xfs_btree_insert(cur, &i);
854                 if (error)
855                         goto out_error;
856                 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error);
857         }
858 
859         trace_xfs_rmap_map_done(mp, cur->bc_private.a.agno, bno, len,
860                         unwritten, oinfo);
861 out_error:
862         if (error)
863                 trace_xfs_rmap_map_error(mp, cur->bc_private.a.agno,
864                                 error, _RET_IP_);
865         return error;
866 }
867 
868 /*
869  * Add a reference to an extent in the rmap btree.
870  */
871 int
872 xfs_rmap_alloc(
873         struct xfs_trans        *tp,
874         struct xfs_buf          *agbp,
875         xfs_agnumber_t          agno,
876         xfs_agblock_t           bno,
877         xfs_extlen_t            len,
878         struct xfs_owner_info   *oinfo)
879 {
880         struct xfs_mount        *mp = tp->t_mountp;
881         struct xfs_btree_cur    *cur;
882         int                     error;
883 
884         if (!xfs_sb_version_hasrmapbt(&mp->m_sb))
885                 return 0;
886 
887         cur = xfs_rmapbt_init_cursor(mp, tp, agbp, agno);
888         error = xfs_rmap_map(cur, bno, len, false, oinfo);
889         if (error)
890                 goto out_error;
891 
892         xfs_btree_del_cursor(cur, XFS_BTREE_NOERROR);
893         return 0;
894 
895 out_error:
896         xfs_btree_del_cursor(cur, XFS_BTREE_ERROR);
897         return error;
898 }
899 
900 #define RMAP_LEFT_CONTIG        (1 << 0)
901 #define RMAP_RIGHT_CONTIG       (1 << 1)
902 #define RMAP_LEFT_FILLING       (1 << 2)
903 #define RMAP_RIGHT_FILLING      (1 << 3)
904 #define RMAP_LEFT_VALID         (1 << 6)
905 #define RMAP_RIGHT_VALID        (1 << 7)
906 
907 #define LEFT            r[0]
908 #define RIGHT           r[1]
909 #define PREV            r[2]
910 #define NEW             r[3]
911 
912 /*
913  * Convert an unwritten extent to a real extent or vice versa.
914  * Does not handle overlapping extents.
915  */
916 STATIC int
917 xfs_rmap_convert(
918         struct xfs_btree_cur    *cur,
919         xfs_agblock_t           bno,
920         xfs_extlen_t            len,
921         bool                    unwritten,
922         struct xfs_owner_info   *oinfo)
923 {
924         struct xfs_mount        *mp = cur->bc_mp;
925         struct xfs_rmap_irec    r[4];   /* neighbor extent entries */
926                                         /* left is 0, right is 1, prev is 2 */
927                                         /* new is 3 */
928         uint64_t                owner;
929         uint64_t                offset;
930         uint64_t                new_endoff;
931         unsigned int            oldext;
932         unsigned int            newext;
933         unsigned int            flags = 0;
934         int                     i;
935         int                     state = 0;
936         int                     error;
937 
938         xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
939         ASSERT(!(XFS_RMAP_NON_INODE_OWNER(owner) ||
940                         (flags & (XFS_RMAP_ATTR_FORK | XFS_RMAP_BMBT_BLOCK))));
941         oldext = unwritten ? XFS_RMAP_UNWRITTEN : 0;
942         new_endoff = offset + len;
943         trace_xfs_rmap_convert(mp, cur->bc_private.a.agno, bno, len,
944                         unwritten, oinfo);
945 
946         /*
947          * For the initial lookup, look for an exact match or the left-adjacent
948          * record for our insertion point. This will also give us the record for
949          * start block contiguity tests.
950          */
951         error = xfs_rmap_lookup_le(cur, bno, len, owner, offset, oldext, &i);
952         if (error)
953                 goto done;
954         XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
955 
956         error = xfs_rmap_get_rec(cur, &PREV, &i);
957         if (error)
958                 goto done;
959         XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
960         trace_xfs_rmap_lookup_le_range_result(cur->bc_mp,
961                         cur->bc_private.a.agno, PREV.rm_startblock,
962                         PREV.rm_blockcount, PREV.rm_owner,
963                         PREV.rm_offset, PREV.rm_flags);
964 
965         ASSERT(PREV.rm_offset <= offset);
966         ASSERT(PREV.rm_offset + PREV.rm_blockcount >= new_endoff);
967         ASSERT((PREV.rm_flags & XFS_RMAP_UNWRITTEN) == oldext);
968         newext = ~oldext & XFS_RMAP_UNWRITTEN;
969 
970         /*
971          * Set flags determining what part of the previous oldext allocation
972          * extent is being replaced by a newext allocation.
973          */
974         if (PREV.rm_offset == offset)
975                 state |= RMAP_LEFT_FILLING;
976         if (PREV.rm_offset + PREV.rm_blockcount == new_endoff)
977                 state |= RMAP_RIGHT_FILLING;
978 
979         /*
980          * Decrement the cursor to see if we have a left-adjacent record to our
981          * insertion point. This will give us the record for end block
982          * contiguity tests.
983          */
984         error = xfs_btree_decrement(cur, 0, &i);
985         if (error)
986                 goto done;
987         if (i) {
988                 state |= RMAP_LEFT_VALID;
989                 error = xfs_rmap_get_rec(cur, &LEFT, &i);
990                 if (error)
991                         goto done;
992                 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
993                 XFS_WANT_CORRUPTED_GOTO(mp,
994                                 LEFT.rm_startblock + LEFT.rm_blockcount <= bno,
995                                 done);
996                 trace_xfs_rmap_find_left_neighbor_result(cur->bc_mp,
997                                 cur->bc_private.a.agno, LEFT.rm_startblock,
998                                 LEFT.rm_blockcount, LEFT.rm_owner,
999                                 LEFT.rm_offset, LEFT.rm_flags);
1000                 if (LEFT.rm_startblock + LEFT.rm_blockcount == bno &&
1001                     LEFT.rm_offset + LEFT.rm_blockcount == offset &&
1002                     xfs_rmap_is_mergeable(&LEFT, owner, newext))
1003                         state |= RMAP_LEFT_CONTIG;
1004         }
1005 
1006         /*
1007          * Increment the cursor to see if we have a right-adjacent record to our
1008          * insertion point. This will give us the record for end block
1009          * contiguity tests.
1010          */
1011         error = xfs_btree_increment(cur, 0, &i);
1012         if (error)
1013                 goto done;
1014         XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1015         error = xfs_btree_increment(cur, 0, &i);
1016         if (error)
1017                 goto done;
1018         if (i) {
1019                 state |= RMAP_RIGHT_VALID;
1020                 error = xfs_rmap_get_rec(cur, &RIGHT, &i);
1021                 if (error)
1022                         goto done;
1023                 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1024                 XFS_WANT_CORRUPTED_GOTO(mp, bno + len <= RIGHT.rm_startblock,
1025                                         done);
1026                 trace_xfs_rmap_find_right_neighbor_result(cur->bc_mp,
1027                                 cur->bc_private.a.agno, RIGHT.rm_startblock,
1028                                 RIGHT.rm_blockcount, RIGHT.rm_owner,
1029                                 RIGHT.rm_offset, RIGHT.rm_flags);
1030                 if (bno + len == RIGHT.rm_startblock &&
1031                     offset + len == RIGHT.rm_offset &&
1032                     xfs_rmap_is_mergeable(&RIGHT, owner, newext))
1033                         state |= RMAP_RIGHT_CONTIG;
1034         }
1035 
1036         /* check that left + prev + right is not too long */
1037         if ((state & (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1038                          RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG)) ==
1039             (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1040              RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG) &&
1041             (unsigned long)LEFT.rm_blockcount + len +
1042              RIGHT.rm_blockcount > XFS_RMAP_LEN_MAX)
1043                 state &= ~RMAP_RIGHT_CONTIG;
1044 
1045         trace_xfs_rmap_convert_state(mp, cur->bc_private.a.agno, state,
1046                         _RET_IP_);
1047 
1048         /* reset the cursor back to PREV */
1049         error = xfs_rmap_lookup_le(cur, bno, len, owner, offset, oldext, &i);
1050         if (error)
1051                 goto done;
1052         XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1053 
1054         /*
1055          * Switch out based on the FILLING and CONTIG state bits.
1056          */
1057         switch (state & (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1058                          RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG)) {
1059         case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1060              RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG:
1061                 /*
1062                  * Setting all of a previous oldext extent to newext.
1063                  * The left and right neighbors are both contiguous with new.
1064                  */
1065                 error = xfs_btree_increment(cur, 0, &i);
1066                 if (error)
1067                         goto done;
1068                 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1069                 trace_xfs_rmap_delete(mp, cur->bc_private.a.agno,
1070                                 RIGHT.rm_startblock, RIGHT.rm_blockcount,
1071                                 RIGHT.rm_owner, RIGHT.rm_offset,
1072                                 RIGHT.rm_flags);
1073                 error = xfs_btree_delete(cur, &i);
1074                 if (error)
1075                         goto done;
1076                 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1077                 error = xfs_btree_decrement(cur, 0, &i);
1078                 if (error)
1079                         goto done;
1080                 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1081                 trace_xfs_rmap_delete(mp, cur->bc_private.a.agno,
1082                                 PREV.rm_startblock, PREV.rm_blockcount,
1083                                 PREV.rm_owner, PREV.rm_offset,
1084                                 PREV.rm_flags);
1085                 error = xfs_btree_delete(cur, &i);
1086                 if (error)
1087                         goto done;
1088                 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1089                 error = xfs_btree_decrement(cur, 0, &i);
1090                 if (error)
1091                         goto done;
1092                 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1093                 NEW = LEFT;
1094                 NEW.rm_blockcount += PREV.rm_blockcount + RIGHT.rm_blockcount;
1095                 error = xfs_rmap_update(cur, &NEW);
1096                 if (error)
1097                         goto done;
1098                 break;
1099 
1100         case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG:
1101                 /*
1102                  * Setting all of a previous oldext extent to newext.
1103                  * The left neighbor is contiguous, the right is not.
1104                  */
1105                 trace_xfs_rmap_delete(mp, cur->bc_private.a.agno,
1106                                 PREV.rm_startblock, PREV.rm_blockcount,
1107                                 PREV.rm_owner, PREV.rm_offset,
1108                                 PREV.rm_flags);
1109                 error = xfs_btree_delete(cur, &i);
1110                 if (error)
1111                         goto done;
1112                 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1113                 error = xfs_btree_decrement(cur, 0, &i);
1114                 if (error)
1115                         goto done;
1116                 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1117                 NEW = LEFT;
1118                 NEW.rm_blockcount += PREV.rm_blockcount;
1119                 error = xfs_rmap_update(cur, &NEW);
1120                 if (error)
1121                         goto done;
1122                 break;
1123 
1124         case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG:
1125                 /*
1126                  * Setting all of a previous oldext extent to newext.
1127                  * The right neighbor is contiguous, the left is not.
1128                  */
1129                 error = xfs_btree_increment(cur, 0, &i);
1130                 if (error)
1131                         goto done;
1132                 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1133                 trace_xfs_rmap_delete(mp, cur->bc_private.a.agno,
1134                                 RIGHT.rm_startblock, RIGHT.rm_blockcount,
1135                                 RIGHT.rm_owner, RIGHT.rm_offset,
1136                                 RIGHT.rm_flags);
1137                 error = xfs_btree_delete(cur, &i);
1138                 if (error)
1139                         goto done;
1140                 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1141                 error = xfs_btree_decrement(cur, 0, &i);
1142                 if (error)
1143                         goto done;
1144                 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1145                 NEW = PREV;
1146                 NEW.rm_blockcount = len + RIGHT.rm_blockcount;
1147                 NEW.rm_flags = newext;
1148                 error = xfs_rmap_update(cur, &NEW);
1149                 if (error)
1150                         goto done;
1151                 break;
1152 
1153         case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING:
1154                 /*
1155                  * Setting all of a previous oldext extent to newext.
1156                  * Neither the left nor right neighbors are contiguous with
1157                  * the new one.
1158                  */
1159                 NEW = PREV;
1160                 NEW.rm_flags = newext;
1161                 error = xfs_rmap_update(cur, &NEW);
1162                 if (error)
1163                         goto done;
1164                 break;
1165 
1166         case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG:
1167                 /*
1168                  * Setting the first part of a previous oldext extent to newext.
1169                  * The left neighbor is contiguous.
1170                  */
1171                 NEW = PREV;
1172                 NEW.rm_offset += len;
1173                 NEW.rm_startblock += len;
1174                 NEW.rm_blockcount -= len;
1175                 error = xfs_rmap_update(cur, &NEW);
1176                 if (error)
1177                         goto done;
1178                 error = xfs_btree_decrement(cur, 0, &i);
1179                 if (error)
1180                         goto done;
1181                 NEW = LEFT;
1182                 NEW.rm_blockcount += len;
1183                 error = xfs_rmap_update(cur, &NEW);
1184                 if (error)
1185                         goto done;
1186                 break;
1187 
1188         case RMAP_LEFT_FILLING:
1189                 /*
1190                  * Setting the first part of a previous oldext extent to newext.
1191                  * The left neighbor is not contiguous.
1192                  */
1193                 NEW = PREV;
1194                 NEW.rm_startblock += len;
1195                 NEW.rm_offset += len;
1196                 NEW.rm_blockcount -= len;
1197                 error = xfs_rmap_update(cur, &NEW);
1198                 if (error)
1199                         goto done;
1200                 NEW.rm_startblock = bno;
1201                 NEW.rm_owner = owner;
1202                 NEW.rm_offset = offset;
1203                 NEW.rm_blockcount = len;
1204                 NEW.rm_flags = newext;
1205                 cur->bc_rec.r = NEW;
1206                 trace_xfs_rmap_insert(mp, cur->bc_private.a.agno, bno,
1207                                 len, owner, offset, newext);
1208                 error = xfs_btree_insert(cur, &i);
1209                 if (error)
1210                         goto done;
1211                 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1212                 break;
1213 
1214         case RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG:
1215                 /*
1216                  * Setting the last part of a previous oldext extent to newext.
1217                  * The right neighbor is contiguous with the new allocation.
1218                  */
1219                 NEW = PREV;
1220                 NEW.rm_blockcount -= len;
1221                 error = xfs_rmap_update(cur, &NEW);
1222                 if (error)
1223                         goto done;
1224                 error = xfs_btree_increment(cur, 0, &i);
1225                 if (error)
1226                         goto done;
1227                 NEW = RIGHT;
1228                 NEW.rm_offset = offset;
1229                 NEW.rm_startblock = bno;
1230                 NEW.rm_blockcount += len;
1231                 error = xfs_rmap_update(cur, &NEW);
1232                 if (error)
1233                         goto done;
1234                 break;
1235 
1236         case RMAP_RIGHT_FILLING:
1237                 /*
1238                  * Setting the last part of a previous oldext extent to newext.
1239                  * The right neighbor is not contiguous.
1240                  */
1241                 NEW = PREV;
1242                 NEW.rm_blockcount -= len;
1243                 error = xfs_rmap_update(cur, &NEW);
1244                 if (error)
1245                         goto done;
1246                 error = xfs_rmap_lookup_eq(cur, bno, len, owner, offset,
1247                                 oldext, &i);
1248                 if (error)
1249                         goto done;
1250                 XFS_WANT_CORRUPTED_GOTO(mp, i == 0, done);
1251                 NEW.rm_startblock = bno;
1252                 NEW.rm_owner = owner;
1253                 NEW.rm_offset = offset;
1254                 NEW.rm_blockcount = len;
1255                 NEW.rm_flags = newext;
1256                 cur->bc_rec.r = NEW;
1257                 trace_xfs_rmap_insert(mp, cur->bc_private.a.agno, bno,
1258                                 len, owner, offset, newext);
1259                 error = xfs_btree_insert(cur, &i);
1260                 if (error)
1261                         goto done;
1262                 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1263                 break;
1264 
1265         case 0:
1266                 /*
1267                  * Setting the middle part of a previous oldext extent to
1268                  * newext.  Contiguity is impossible here.
1269                  * One extent becomes three extents.
1270                  */
1271                 /* new right extent - oldext */
1272                 NEW.rm_startblock = bno + len;
1273                 NEW.rm_owner = owner;
1274                 NEW.rm_offset = new_endoff;
1275                 NEW.rm_blockcount = PREV.rm_offset + PREV.rm_blockcount -
1276                                 new_endoff;
1277                 NEW.rm_flags = PREV.rm_flags;
1278                 error = xfs_rmap_update(cur, &NEW);
1279                 if (error)
1280                         goto done;
1281                 /* new left extent - oldext */
1282                 NEW = PREV;
1283                 NEW.rm_blockcount = offset - PREV.rm_offset;
1284                 cur->bc_rec.r = NEW;
1285                 trace_xfs_rmap_insert(mp, cur->bc_private.a.agno,
1286                                 NEW.rm_startblock, NEW.rm_blockcount,
1287                                 NEW.rm_owner, NEW.rm_offset,
1288                                 NEW.rm_flags);
1289                 error = xfs_btree_insert(cur, &i);
1290                 if (error)
1291                         goto done;
1292                 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1293                 /*
1294                  * Reset the cursor to the position of the new extent
1295                  * we are about to insert as we can't trust it after
1296                  * the previous insert.
1297                  */
1298                 error = xfs_rmap_lookup_eq(cur, bno, len, owner, offset,
1299                                 oldext, &i);
1300                 if (error)
1301                         goto done;
1302                 XFS_WANT_CORRUPTED_GOTO(mp, i == 0, done);
1303                 /* new middle extent - newext */
1304                 cur->bc_rec.r.rm_flags &= ~XFS_RMAP_UNWRITTEN;
1305                 cur->bc_rec.r.rm_flags |= newext;
1306                 trace_xfs_rmap_insert(mp, cur->bc_private.a.agno, bno, len,
1307                                 owner, offset, newext);
1308                 error = xfs_btree_insert(cur, &i);
1309                 if (error)
1310                         goto done;
1311                 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1312                 break;
1313 
1314         case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG:
1315         case RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG:
1316         case RMAP_LEFT_FILLING | RMAP_RIGHT_CONTIG:
1317         case RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG:
1318         case RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG:
1319         case RMAP_LEFT_CONTIG:
1320         case RMAP_RIGHT_CONTIG:
1321                 /*
1322                  * These cases are all impossible.
1323                  */
1324                 ASSERT(0);
1325         }
1326 
1327         trace_xfs_rmap_convert_done(mp, cur->bc_private.a.agno, bno, len,
1328                         unwritten, oinfo);
1329 done:
1330         if (error)
1331                 trace_xfs_rmap_convert_error(cur->bc_mp,
1332                                 cur->bc_private.a.agno, error, _RET_IP_);
1333         return error;
1334 }
1335 
1336 /*
1337  * Convert an unwritten extent to a real extent or vice versa.  If there is no
1338  * possibility of overlapping extents, delegate to the simpler convert
1339  * function.
1340  */
1341 STATIC int
1342 xfs_rmap_convert_shared(
1343         struct xfs_btree_cur    *cur,
1344         xfs_agblock_t           bno,
1345         xfs_extlen_t            len,
1346         bool                    unwritten,
1347         struct xfs_owner_info   *oinfo)
1348 {
1349         struct xfs_mount        *mp = cur->bc_mp;
1350         struct xfs_rmap_irec    r[4];   /* neighbor extent entries */
1351                                         /* left is 0, right is 1, prev is 2 */
1352                                         /* new is 3 */
1353         uint64_t                owner;
1354         uint64_t                offset;
1355         uint64_t                new_endoff;
1356         unsigned int            oldext;
1357         unsigned int            newext;
1358         unsigned int            flags = 0;
1359         int                     i;
1360         int                     state = 0;
1361         int                     error;
1362 
1363         xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
1364         ASSERT(!(XFS_RMAP_NON_INODE_OWNER(owner) ||
1365                         (flags & (XFS_RMAP_ATTR_FORK | XFS_RMAP_BMBT_BLOCK))));
1366         oldext = unwritten ? XFS_RMAP_UNWRITTEN : 0;
1367         new_endoff = offset + len;
1368         trace_xfs_rmap_convert(mp, cur->bc_private.a.agno, bno, len,
1369                         unwritten, oinfo);
1370 
1371         /*
1372          * For the initial lookup, look for and exact match or the left-adjacent
1373          * record for our insertion point. This will also give us the record for
1374          * start block contiguity tests.
1375          */
1376         error = xfs_rmap_lookup_le_range(cur, bno, owner, offset, flags,
1377                         &PREV, &i);
1378         XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1379 
1380         ASSERT(PREV.rm_offset <= offset);
1381         ASSERT(PREV.rm_offset + PREV.rm_blockcount >= new_endoff);
1382         ASSERT((PREV.rm_flags & XFS_RMAP_UNWRITTEN) == oldext);
1383         newext = ~oldext & XFS_RMAP_UNWRITTEN;
1384 
1385         /*
1386          * Set flags determining what part of the previous oldext allocation
1387          * extent is being replaced by a newext allocation.
1388          */
1389         if (PREV.rm_offset == offset)
1390                 state |= RMAP_LEFT_FILLING;
1391         if (PREV.rm_offset + PREV.rm_blockcount == new_endoff)
1392                 state |= RMAP_RIGHT_FILLING;
1393 
1394         /* Is there a left record that abuts our range? */
1395         error = xfs_rmap_find_left_neighbor(cur, bno, owner, offset, newext,
1396                         &LEFT, &i);
1397         if (error)
1398                 goto done;
1399         if (i) {
1400                 state |= RMAP_LEFT_VALID;
1401                 XFS_WANT_CORRUPTED_GOTO(mp,
1402                                 LEFT.rm_startblock + LEFT.rm_blockcount <= bno,
1403                                 done);
1404                 if (xfs_rmap_is_mergeable(&LEFT, owner, newext))
1405                         state |= RMAP_LEFT_CONTIG;
1406         }
1407 
1408         /* Is there a right record that abuts our range? */
1409         error = xfs_rmap_lookup_eq(cur, bno + len, len, owner, offset + len,
1410                         newext, &i);
1411         if (error)
1412                 goto done;
1413         if (i) {
1414                 state |= RMAP_RIGHT_VALID;
1415                 error = xfs_rmap_get_rec(cur, &RIGHT, &i);
1416                 if (error)
1417                         goto done;
1418                 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1419                 XFS_WANT_CORRUPTED_GOTO(mp, bno + len <= RIGHT.rm_startblock,
1420                                 done);
1421                 trace_xfs_rmap_find_right_neighbor_result(cur->bc_mp,
1422                                 cur->bc_private.a.agno, RIGHT.rm_startblock,
1423                                 RIGHT.rm_blockcount, RIGHT.rm_owner,
1424                                 RIGHT.rm_offset, RIGHT.rm_flags);
1425                 if (xfs_rmap_is_mergeable(&RIGHT, owner, newext))
1426                         state |= RMAP_RIGHT_CONTIG;
1427         }
1428 
1429         /* check that left + prev + right is not too long */
1430         if ((state & (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1431                          RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG)) ==
1432             (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1433              RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG) &&
1434             (unsigned long)LEFT.rm_blockcount + len +
1435              RIGHT.rm_blockcount > XFS_RMAP_LEN_MAX)
1436                 state &= ~RMAP_RIGHT_CONTIG;
1437 
1438         trace_xfs_rmap_convert_state(mp, cur->bc_private.a.agno, state,
1439                         _RET_IP_);
1440         /*
1441          * Switch out based on the FILLING and CONTIG state bits.
1442          */
1443         switch (state & (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1444                          RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG)) {
1445         case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1446              RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG:
1447                 /*
1448                  * Setting all of a previous oldext extent to newext.
1449                  * The left and right neighbors are both contiguous with new.
1450                  */
1451                 error = xfs_rmap_delete(cur, RIGHT.rm_startblock,
1452                                 RIGHT.rm_blockcount, RIGHT.rm_owner,
1453                                 RIGHT.rm_offset, RIGHT.rm_flags);
1454                 if (error)
1455                         goto done;
1456                 error = xfs_rmap_delete(cur, PREV.rm_startblock,
1457                                 PREV.rm_blockcount, PREV.rm_owner,
1458                                 PREV.rm_offset, PREV.rm_flags);
1459                 if (error)
1460                         goto done;
1461                 NEW = LEFT;
1462                 error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1463                                 NEW.rm_blockcount, NEW.rm_owner,
1464                                 NEW.rm_offset, NEW.rm_flags, &i);
1465                 if (error)
1466                         goto done;
1467                 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1468                 NEW.rm_blockcount += PREV.rm_blockcount + RIGHT.rm_blockcount;
1469                 error = xfs_rmap_update(cur, &NEW);
1470                 if (error)
1471                         goto done;
1472                 break;
1473 
1474         case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG:
1475                 /*
1476                  * Setting all of a previous oldext extent to newext.
1477                  * The left neighbor is contiguous, the right is not.
1478                  */
1479                 error = xfs_rmap_delete(cur, PREV.rm_startblock,
1480                                 PREV.rm_blockcount, PREV.rm_owner,
1481                                 PREV.rm_offset, PREV.rm_flags);
1482                 if (error)
1483                         goto done;
1484                 NEW = LEFT;
1485                 error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1486                                 NEW.rm_blockcount, NEW.rm_owner,
1487                                 NEW.rm_offset, NEW.rm_flags, &i);
1488                 if (error)
1489                         goto done;
1490                 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1491                 NEW.rm_blockcount += PREV.rm_blockcount;
1492                 error = xfs_rmap_update(cur, &NEW);
1493                 if (error)
1494                         goto done;
1495                 break;
1496 
1497         case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG:
1498                 /*
1499                  * Setting all of a previous oldext extent to newext.
1500                  * The right neighbor is contiguous, the left is not.
1501                  */
1502                 error = xfs_rmap_delete(cur, RIGHT.rm_startblock,
1503                                 RIGHT.rm_blockcount, RIGHT.rm_owner,
1504                                 RIGHT.rm_offset, RIGHT.rm_flags);
1505                 if (error)
1506                         goto done;
1507                 NEW = PREV;
1508                 error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1509                                 NEW.rm_blockcount, NEW.rm_owner,
1510                                 NEW.rm_offset, NEW.rm_flags, &i);
1511                 if (error)
1512                         goto done;
1513                 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1514                 NEW.rm_blockcount += RIGHT.rm_blockcount;
1515                 NEW.rm_flags = RIGHT.rm_flags;
1516                 error = xfs_rmap_update(cur, &NEW);
1517                 if (error)
1518                         goto done;
1519                 break;
1520 
1521         case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING:
1522                 /*
1523                  * Setting all of a previous oldext extent to newext.
1524                  * Neither the left nor right neighbors are contiguous with
1525                  * the new one.
1526                  */
1527                 NEW = PREV;
1528                 error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1529                                 NEW.rm_blockcount, NEW.rm_owner,
1530                                 NEW.rm_offset, NEW.rm_flags, &i);
1531                 if (error)
1532                         goto done;
1533                 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1534                 NEW.rm_flags = newext;
1535                 error = xfs_rmap_update(cur, &NEW);
1536                 if (error)
1537                         goto done;
1538                 break;
1539 
1540         case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG:
1541                 /*
1542                  * Setting the first part of a previous oldext extent to newext.
1543                  * The left neighbor is contiguous.
1544                  */
1545                 NEW = PREV;
1546                 error = xfs_rmap_delete(cur, NEW.rm_startblock,
1547                                 NEW.rm_blockcount, NEW.rm_owner,
1548                                 NEW.rm_offset, NEW.rm_flags);
1549                 if (error)
1550                         goto done;
1551                 NEW.rm_offset += len;
1552                 NEW.rm_startblock += len;
1553                 NEW.rm_blockcount -= len;
1554                 error = xfs_rmap_insert(cur, NEW.rm_startblock,
1555                                 NEW.rm_blockcount, NEW.rm_owner,
1556                                 NEW.rm_offset, NEW.rm_flags);
1557                 if (error)
1558                         goto done;
1559                 NEW = LEFT;
1560                 error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1561                                 NEW.rm_blockcount, NEW.rm_owner,
1562                                 NEW.rm_offset, NEW.rm_flags, &i);
1563                 if (error)
1564                         goto done;
1565                 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1566                 NEW.rm_blockcount += len;
1567                 error = xfs_rmap_update(cur, &NEW);
1568                 if (error)
1569                         goto done;
1570                 break;
1571 
1572         case RMAP_LEFT_FILLING:
1573                 /*
1574                  * Setting the first part of a previous oldext extent to newext.
1575                  * The left neighbor is not contiguous.
1576                  */
1577                 NEW = PREV;
1578                 error = xfs_rmap_delete(cur, NEW.rm_startblock,
1579                                 NEW.rm_blockcount, NEW.rm_owner,
1580                                 NEW.rm_offset, NEW.rm_flags);
1581                 if (error)
1582                         goto done;
1583                 NEW.rm_offset += len;
1584                 NEW.rm_startblock += len;
1585                 NEW.rm_blockcount -= len;
1586                 error = xfs_rmap_insert(cur, NEW.rm_startblock,
1587                                 NEW.rm_blockcount, NEW.rm_owner,
1588                                 NEW.rm_offset, NEW.rm_flags);
1589                 if (error)
1590                         goto done;
1591                 error = xfs_rmap_insert(cur, bno, len, owner, offset, newext);
1592                 if (error)
1593                         goto done;
1594                 break;
1595 
1596         case RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG:
1597                 /*
1598                  * Setting the last part of a previous oldext extent to newext.
1599                  * The right neighbor is contiguous with the new allocation.
1600                  */
1601                 NEW = PREV;
1602                 error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1603                                 NEW.rm_blockcount, NEW.rm_owner,
1604                                 NEW.rm_offset, NEW.rm_flags, &i);
1605                 if (error)
1606                         goto done;
1607                 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1608                 NEW.rm_blockcount = offset - NEW.rm_offset;
1609                 error = xfs_rmap_update(cur, &NEW);
1610                 if (error)
1611                         goto done;
1612                 NEW = RIGHT;
1613                 error = xfs_rmap_delete(cur, NEW.rm_startblock,
1614                                 NEW.rm_blockcount, NEW.rm_owner,
1615                                 NEW.rm_offset, NEW.rm_flags);
1616                 if (error)
1617                         goto done;
1618                 NEW.rm_offset = offset;
1619                 NEW.rm_startblock = bno;
1620                 NEW.rm_blockcount += len;
1621                 error = xfs_rmap_insert(cur, NEW.rm_startblock,
1622                                 NEW.rm_blockcount, NEW.rm_owner,
1623                                 NEW.rm_offset, NEW.rm_flags);
1624                 if (error)
1625                         goto done;
1626                 break;
1627 
1628         case RMAP_RIGHT_FILLING:
1629                 /*
1630                  * Setting the last part of a previous oldext extent to newext.
1631                  * The right neighbor is not contiguous.
1632                  */
1633                 NEW = PREV;
1634                 error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1635                                 NEW.rm_blockcount, NEW.rm_owner,
1636                                 NEW.rm_offset, NEW.rm_flags, &i);
1637                 if (error)
1638                         goto done;
1639                 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1640                 NEW.rm_blockcount -= len;
1641                 error = xfs_rmap_update(cur, &NEW);
1642                 if (error)
1643                         goto done;
1644                 error = xfs_rmap_insert(cur, bno, len, owner, offset, newext);
1645                 if (error)
1646                         goto done;
1647                 break;
1648 
1649         case 0:
1650                 /*
1651                  * Setting the middle part of a previous oldext extent to
1652                  * newext.  Contiguity is impossible here.
1653                  * One extent becomes three extents.
1654                  */
1655                 /* new right extent - oldext */
1656                 NEW.rm_startblock = bno + len;
1657                 NEW.rm_owner = owner;
1658                 NEW.rm_offset = new_endoff;
1659                 NEW.rm_blockcount = PREV.rm_offset + PREV.rm_blockcount -
1660                                 new_endoff;
1661                 NEW.rm_flags = PREV.rm_flags;
1662                 error = xfs_rmap_insert(cur, NEW.rm_startblock,
1663                                 NEW.rm_blockcount, NEW.rm_owner, NEW.rm_offset,
1664                                 NEW.rm_flags);
1665                 if (error)
1666                         goto done;
1667                 /* new left extent - oldext */
1668                 NEW = PREV;
1669                 error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1670                                 NEW.rm_blockcount, NEW.rm_owner,
1671                                 NEW.rm_offset, NEW.rm_flags, &i);
1672                 if (error)
1673                         goto done;
1674                 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done);
1675                 NEW.rm_blockcount = offset - NEW.rm_offset;
1676                 error = xfs_rmap_update(cur, &NEW);
1677                 if (error)
1678                         goto done;
1679                 /* new middle extent - newext */
1680                 NEW.rm_startblock = bno;
1681                 NEW.rm_blockcount = len;
1682                 NEW.rm_owner = owner;
1683                 NEW.rm_offset = offset;
1684                 NEW.rm_flags = newext;
1685                 error = xfs_rmap_insert(cur, NEW.rm_startblock,
1686                                 NEW.rm_blockcount, NEW.rm_owner, NEW.rm_offset,
1687                                 NEW.rm_flags);
1688                 if (error)
1689                         goto done;
1690                 break;
1691 
1692         case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG:
1693         case RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG:
1694         case RMAP_LEFT_FILLING | RMAP_RIGHT_CONTIG:
1695         case RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG:
1696         case RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG:
1697         case RMAP_LEFT_CONTIG:
1698         case RMAP_RIGHT_CONTIG:
1699                 /*
1700                  * These cases are all impossible.
1701                  */
1702                 ASSERT(0);
1703         }
1704 
1705         trace_xfs_rmap_convert_done(mp, cur->bc_private.a.agno, bno, len,
1706                         unwritten, oinfo);
1707 done:
1708         if (error)
1709                 trace_xfs_rmap_convert_error(cur->bc_mp,
1710                                 cur->bc_private.a.agno, error, _RET_IP_);
1711         return error;
1712 }
1713 
1714 #undef  NEW
1715 #undef  LEFT
1716 #undef  RIGHT
1717 #undef  PREV
1718 
1719 /*
1720  * Find an extent in the rmap btree and unmap it.  For rmap extent types that
1721  * can overlap (data fork rmaps on reflink filesystems) we must be careful
1722  * that the prev/next records in the btree might belong to another owner.
1723  * Therefore we must use delete+insert to alter any of the key fields.
1724  *
1725  * For every other situation there can only be one owner for a given extent,
1726  * so we can call the regular _free function.
1727  */
1728 STATIC int
1729 xfs_rmap_unmap_shared(
1730         struct xfs_btree_cur    *cur,
1731         xfs_agblock_t           bno,
1732         xfs_extlen_t            len,
1733         bool                    unwritten,
1734         struct xfs_owner_info   *oinfo)
1735 {
1736         struct xfs_mount        *mp = cur->bc_mp;
1737         struct xfs_rmap_irec    ltrec;
1738         uint64_t                ltoff;
1739         int                     error = 0;
1740         int                     i;
1741         uint64_t                owner;
1742         uint64_t                offset;
1743         unsigned int            flags;
1744 
1745         xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
1746         if (unwritten)
1747                 flags |= XFS_RMAP_UNWRITTEN;
1748         trace_xfs_rmap_unmap(mp, cur->bc_private.a.agno, bno, len,
1749                         unwritten, oinfo);
1750 
1751         /*
1752          * We should always have a left record because there's a static record
1753          * for the AG headers at rm_startblock == 0 created by mkfs/growfs that
1754          * will not ever be removed from the tree.
1755          */
1756         error = xfs_rmap_lookup_le_range(cur, bno, owner, offset, flags,
1757                         &ltrec, &i);
1758         if (error)
1759                 goto out_error;
1760         XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error);
1761         ltoff = ltrec.rm_offset;
1762 
1763         /* Make sure the extent we found covers the entire freeing range. */
1764         XFS_WANT_CORRUPTED_GOTO(mp, ltrec.rm_startblock <= bno &&
1765                 ltrec.rm_startblock + ltrec.rm_blockcount >=
1766                 bno + len, out_error);
1767 
1768         /* Make sure the owner matches what we expect to find in the tree. */
1769         XFS_WANT_CORRUPTED_GOTO(mp, owner == ltrec.rm_owner, out_error);
1770 
1771         /* Make sure the unwritten flag matches. */
1772         XFS_WANT_CORRUPTED_GOTO(mp, (flags & XFS_RMAP_UNWRITTEN) ==
1773                         (ltrec.rm_flags & XFS_RMAP_UNWRITTEN), out_error);
1774 
1775         /* Check the offset. */
1776         XFS_WANT_CORRUPTED_GOTO(mp, ltrec.rm_offset <= offset, out_error);
1777         XFS_WANT_CORRUPTED_GOTO(mp, offset <= ltoff + ltrec.rm_blockcount,
1778                         out_error);
1779 
1780         if (ltrec.rm_startblock == bno && ltrec.rm_blockcount == len) {
1781                 /* Exact match, simply remove the record from rmap tree. */
1782                 error = xfs_rmap_delete(cur, ltrec.rm_startblock,
1783                                 ltrec.rm_blockcount, ltrec.rm_owner,
1784                                 ltrec.rm_offset, ltrec.rm_flags);
1785                 if (error)
1786                         goto out_error;
1787         } else if (ltrec.rm_startblock == bno) {
1788                 /*
1789                  * Overlap left hand side of extent: move the start, trim the
1790                  * length and update the current record.
1791                  *
1792                  *       ltbno                ltlen
1793                  * Orig:    |oooooooooooooooooooo|
1794                  * Freeing: |fffffffff|
1795                  * Result:            |rrrrrrrrrr|
1796                  *         bno       len
1797                  */
1798 
1799                 /* Delete prev rmap. */
1800                 error = xfs_rmap_delete(cur, ltrec.rm_startblock,
1801                                 ltrec.rm_blockcount, ltrec.rm_owner,
1802                                 ltrec.rm_offset, ltrec.rm_flags);
1803                 if (error)
1804                         goto out_error;
1805 
1806                 /* Add an rmap at the new offset. */
1807                 ltrec.rm_startblock += len;
1808                 ltrec.rm_blockcount -= len;
1809                 ltrec.rm_offset += len;
1810                 error = xfs_rmap_insert(cur, ltrec.rm_startblock,
1811                                 ltrec.rm_blockcount, ltrec.rm_owner,
1812                                 ltrec.rm_offset, ltrec.rm_flags);
1813                 if (error)
1814                         goto out_error;
1815         } else if (ltrec.rm_startblock + ltrec.rm_blockcount == bno + len) {
1816                 /*
1817                  * Overlap right hand side of extent: trim the length and
1818                  * update the current record.
1819                  *
1820                  *       ltbno                ltlen
1821                  * Orig:    |oooooooooooooooooooo|
1822                  * Freeing:            |fffffffff|
1823                  * Result:  |rrrrrrrrrr|
1824                  *                    bno       len
1825                  */
1826                 error = xfs_rmap_lookup_eq(cur, ltrec.rm_startblock,
1827                                 ltrec.rm_blockcount, ltrec.rm_owner,
1828                                 ltrec.rm_offset, ltrec.rm_flags, &i);
1829                 if (error)
1830                         goto out_error;
1831                 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error);
1832                 ltrec.rm_blockcount -= len;
1833                 error = xfs_rmap_update(cur, &ltrec);
1834                 if (error)
1835                         goto out_error;
1836         } else {
1837                 /*
1838                  * Overlap middle of extent: trim the length of the existing
1839                  * record to the length of the new left-extent size, increment
1840                  * the insertion position so we can insert a new record
1841                  * containing the remaining right-extent space.
1842                  *
1843                  *       ltbno                ltlen
1844                  * Orig:    |oooooooooooooooooooo|
1845                  * Freeing:       |fffffffff|
1846                  * Result:  |rrrrr|         |rrrr|
1847                  *               bno       len
1848                  */
1849                 xfs_extlen_t    orig_len = ltrec.rm_blockcount;
1850 
1851                 /* Shrink the left side of the rmap */
1852                 error = xfs_rmap_lookup_eq(cur, ltrec.rm_startblock,
1853                                 ltrec.rm_blockcount, ltrec.rm_owner,
1854                                 ltrec.rm_offset, ltrec.rm_flags, &i);
1855                 if (error)
1856                         goto out_error;
1857                 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error);
1858                 ltrec.rm_blockcount = bno - ltrec.rm_startblock;
1859                 error = xfs_rmap_update(cur, &ltrec);
1860                 if (error)
1861                         goto out_error;
1862 
1863                 /* Add an rmap at the new offset */
1864                 error = xfs_rmap_insert(cur, bno + len,
1865                                 orig_len - len - ltrec.rm_blockcount,
1866                                 ltrec.rm_owner, offset + len,
1867                                 ltrec.rm_flags);
1868                 if (error)
1869                         goto out_error;
1870         }
1871 
1872         trace_xfs_rmap_unmap_done(mp, cur->bc_private.a.agno, bno, len,
1873                         unwritten, oinfo);
1874 out_error:
1875         if (error)
1876                 trace_xfs_rmap_unmap_error(cur->bc_mp,
1877                                 cur->bc_private.a.agno, error, _RET_IP_);
1878         return error;
1879 }
1880 
1881 /*
1882  * Find an extent in the rmap btree and map it.  For rmap extent types that
1883  * can overlap (data fork rmaps on reflink filesystems) we must be careful
1884  * that the prev/next records in the btree might belong to another owner.
1885  * Therefore we must use delete+insert to alter any of the key fields.
1886  *
1887  * For every other situation there can only be one owner for a given extent,
1888  * so we can call the regular _alloc function.
1889  */
1890 STATIC int
1891 xfs_rmap_map_shared(
1892         struct xfs_btree_cur    *cur,
1893         xfs_agblock_t           bno,
1894         xfs_extlen_t            len,
1895         bool                    unwritten,
1896         struct xfs_owner_info   *oinfo)
1897 {
1898         struct xfs_mount        *mp = cur->bc_mp;
1899         struct xfs_rmap_irec    ltrec;
1900         struct xfs_rmap_irec    gtrec;
1901         int                     have_gt;
1902         int                     have_lt;
1903         int                     error = 0;
1904         int                     i;
1905         uint64_t                owner;
1906         uint64_t                offset;
1907         unsigned int            flags = 0;
1908 
1909         xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
1910         if (unwritten)
1911                 flags |= XFS_RMAP_UNWRITTEN;
1912         trace_xfs_rmap_map(mp, cur->bc_private.a.agno, bno, len,
1913                         unwritten, oinfo);
1914 
1915         /* Is there a left record that abuts our range? */
1916         error = xfs_rmap_find_left_neighbor(cur, bno, owner, offset, flags,
1917                         &ltrec, &have_lt);
1918         if (error)
1919                 goto out_error;
1920         if (have_lt &&
1921             !xfs_rmap_is_mergeable(&ltrec, owner, flags))
1922                 have_lt = 0;
1923 
1924         /* Is there a right record that abuts our range? */
1925         error = xfs_rmap_lookup_eq(cur, bno + len, len, owner, offset + len,
1926                         flags, &have_gt);
1927         if (error)
1928                 goto out_error;
1929         if (have_gt) {
1930                 error = xfs_rmap_get_rec(cur, &gtrec, &have_gt);
1931                 if (error)
1932                         goto out_error;
1933                 XFS_WANT_CORRUPTED_GOTO(mp, have_gt == 1, out_error);
1934                 trace_xfs_rmap_find_right_neighbor_result(cur->bc_mp,
1935                         cur->bc_private.a.agno, gtrec.rm_startblock,
1936                         gtrec.rm_blockcount, gtrec.rm_owner,
1937                         gtrec.rm_offset, gtrec.rm_flags);
1938 
1939                 if (!xfs_rmap_is_mergeable(&gtrec, owner, flags))
1940                         have_gt = 0;
1941         }
1942 
1943         if (have_lt &&
1944             ltrec.rm_startblock + ltrec.rm_blockcount == bno &&
1945             ltrec.rm_offset + ltrec.rm_blockcount == offset) {
1946                 /*
1947                  * Left edge contiguous, merge into left record.
1948                  *
1949                  *       ltbno     ltlen
1950                  * orig:   |ooooooooo|
1951                  * adding:           |aaaaaaaaa|
1952                  * result: |rrrrrrrrrrrrrrrrrrr|
1953                  *                  bno       len
1954                  */
1955                 ltrec.rm_blockcount += len;
1956                 if (have_gt &&
1957                     bno + len == gtrec.rm_startblock &&
1958                     offset + len == gtrec.rm_offset) {
1959                         /*
1960                          * Right edge also contiguous, delete right record
1961                          * and merge into left record.
1962                          *
1963                          *       ltbno     ltlen    gtbno     gtlen
1964                          * orig:   |ooooooooo|         |ooooooooo|
1965                          * adding:           |aaaaaaaaa|
1966                          * result: |rrrrrrrrrrrrrrrrrrrrrrrrrrrrr|
1967                          */
1968                         ltrec.rm_blockcount += gtrec.rm_blockcount;
1969                         error = xfs_rmap_delete(cur, gtrec.rm_startblock,
1970                                         gtrec.rm_blockcount, gtrec.rm_owner,
1971                                         gtrec.rm_offset, gtrec.rm_flags);
1972                         if (error)
1973                                 goto out_error;
1974                 }
1975 
1976                 /* Point the cursor back to the left record and update. */
1977                 error = xfs_rmap_lookup_eq(cur, ltrec.rm_startblock,
1978                                 ltrec.rm_blockcount, ltrec.rm_owner,
1979                                 ltrec.rm_offset, ltrec.rm_flags, &i);
1980                 if (error)
1981                         goto out_error;
1982                 XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error);
1983 
1984                 error = xfs_rmap_update(cur, &ltrec);
1985                 if (error)
1986                         goto out_error;
1987         } else if (have_gt &&
1988                    bno + len == gtrec.rm_startblock &&
1989                    offset + len == gtrec.rm_offset) {
1990                 /*
1991                  * Right edge contiguous, merge into right record.
1992                  *
1993                  *                 gtbno     gtlen
1994                  * Orig:             |ooooooooo|
1995                  * adding: |aaaaaaaaa|
1996                  * Result: |rrrrrrrrrrrrrrrrrrr|
1997                  *        bno       len
1998                  */
1999                 /* Delete the old record. */
2000                 error = xfs_rmap_delete(cur, gtrec.rm_startblock,
2001                                 gtrec.rm_blockcount, gtrec.rm_owner,
2002                                 gtrec.rm_offset, gtrec.rm_flags);
2003                 if (error)
2004                         goto out_error;
2005 
2006                 /* Move the start and re-add it. */
2007                 gtrec.rm_startblock = bno;
2008                 gtrec.rm_blockcount += len;
2009                 gtrec.rm_offset = offset;
2010                 error = xfs_rmap_insert(cur, gtrec.rm_startblock,
2011                                 gtrec.rm_blockcount, gtrec.rm_owner,
2012                                 gtrec.rm_offset, gtrec.rm_flags);
2013                 if (error)
2014                         goto out_error;
2015         } else {
2016                 /*
2017                  * No contiguous edge with identical owner, insert
2018                  * new record at current cursor position.
2019                  */
2020                 error = xfs_rmap_insert(cur, bno, len, owner, offset, flags);
2021                 if (error)
2022                         goto out_error;
2023         }
2024 
2025         trace_xfs_rmap_map_done(mp, cur->bc_private.a.agno, bno, len,
2026                         unwritten, oinfo);
2027 out_error:
2028         if (error)
2029                 trace_xfs_rmap_map_error(cur->bc_mp,
2030                                 cur->bc_private.a.agno, error, _RET_IP_);
2031         return error;
2032 }
2033 
2034 struct xfs_rmap_query_range_info {
2035         xfs_rmap_query_range_fn fn;
2036         void                            *priv;
2037 };
2038 
2039 /* Format btree record and pass to our callback. */
2040 STATIC int
2041 xfs_rmap_query_range_helper(
2042         struct xfs_btree_cur    *cur,
2043         union xfs_btree_rec     *rec,
2044         void                    *priv)
2045 {
2046         struct xfs_rmap_query_range_info        *query = priv;
2047         struct xfs_rmap_irec                    irec;
2048         int                                     error;
2049 
2050         error = xfs_rmap_btrec_to_irec(rec, &irec);
2051         if (error)
2052                 return error;
2053         return query->fn(cur, &irec, query->priv);
2054 }
2055 
2056 /* Find all rmaps between two keys. */
2057 int
2058 xfs_rmap_query_range(
2059         struct xfs_btree_cur                    *cur,
2060         struct xfs_rmap_irec                    *low_rec,
2061         struct xfs_rmap_irec                    *high_rec,
2062         xfs_rmap_query_range_fn                 fn,
2063         void                                    *priv)
2064 {
2065         union xfs_btree_irec                    low_brec;
2066         union xfs_btree_irec                    high_brec;
2067         struct xfs_rmap_query_range_info        query;
2068 
2069         low_brec.r = *low_rec;
2070         high_brec.r = *high_rec;
2071         query.priv = priv;
2072         query.fn = fn;
2073         return xfs_btree_query_range(cur, &low_brec, &high_brec,
2074                         xfs_rmap_query_range_helper, &query);
2075 }
2076 
2077 /* Find all rmaps. */
2078 int
2079 xfs_rmap_query_all(
2080         struct xfs_btree_cur                    *cur,
2081         xfs_rmap_query_range_fn                 fn,
2082         void                                    *priv)
2083 {
2084         struct xfs_rmap_query_range_info        query;
2085 
2086         query.priv = priv;
2087         query.fn = fn;
2088         return xfs_btree_query_all(cur, xfs_rmap_query_range_helper, &query);
2089 }
2090 
2091 /* Clean up after calling xfs_rmap_finish_one. */
2092 void
2093 xfs_rmap_finish_one_cleanup(
2094         struct xfs_trans        *tp,
2095         struct xfs_btree_cur    *rcur,
2096         int                     error)
2097 {
2098         struct xfs_buf          *agbp;
2099 
2100         if (rcur == NULL)
2101                 return;
2102         agbp = rcur->bc_private.a.agbp;
2103         xfs_btree_del_cursor(rcur, error ? XFS_BTREE_ERROR : XFS_BTREE_NOERROR);
2104         if (error)
2105                 xfs_trans_brelse(tp, agbp);
2106 }
2107 
2108 /*
2109  * Process one of the deferred rmap operations.  We pass back the
2110  * btree cursor to maintain our lock on the rmapbt between calls.
2111  * This saves time and eliminates a buffer deadlock between the
2112  * superblock and the AGF because we'll always grab them in the same
2113  * order.
2114  */
2115 int
2116 xfs_rmap_finish_one(
2117         struct xfs_trans                *tp,
2118         enum xfs_rmap_intent_type       type,
2119         uint64_t                        owner,
2120         int                             whichfork,
2121         xfs_fileoff_t                   startoff,
2122         xfs_fsblock_t                   startblock,
2123         xfs_filblks_t                   blockcount,
2124         xfs_exntst_t                    state,
2125         struct xfs_btree_cur            **pcur)
2126 {
2127         struct xfs_mount                *mp = tp->t_mountp;
2128         struct xfs_btree_cur            *rcur;
2129         struct xfs_buf                  *agbp = NULL;
2130         int                             error = 0;
2131         xfs_agnumber_t                  agno;
2132         struct xfs_owner_info           oinfo;
2133         xfs_agblock_t                   bno;
2134         bool                            unwritten;
2135 
2136         agno = XFS_FSB_TO_AGNO(mp, startblock);
2137         ASSERT(agno != NULLAGNUMBER);
2138         bno = XFS_FSB_TO_AGBNO(mp, startblock);
2139 
2140         trace_xfs_rmap_deferred(mp, agno, type, bno, owner, whichfork,
2141                         startoff, blockcount, state);
2142 
2143         if (XFS_TEST_ERROR(false, mp,
2144                         XFS_ERRTAG_RMAP_FINISH_ONE))
2145                 return -EIO;
2146 
2147         /*
2148          * If we haven't gotten a cursor or the cursor AG doesn't match
2149          * the startblock, get one now.
2150          */
2151         rcur = *pcur;
2152         if (rcur != NULL && rcur->bc_private.a.agno != agno) {
2153                 xfs_rmap_finish_one_cleanup(tp, rcur, 0);
2154                 rcur = NULL;
2155                 *pcur = NULL;
2156         }
2157         if (rcur == NULL) {
2158                 /*
2159                  * Refresh the freelist before we start changing the
2160                  * rmapbt, because a shape change could cause us to
2161                  * allocate blocks.
2162                  */
2163                 error = xfs_free_extent_fix_freelist(tp, agno, &agbp);
2164                 if (error)
2165                         return error;
2166                 if (!agbp)
2167                         return -EFSCORRUPTED;
2168 
2169                 rcur = xfs_rmapbt_init_cursor(mp, tp, agbp, agno);
2170                 if (!rcur) {
2171                         error = -ENOMEM;
2172                         goto out_cur;
2173                 }
2174         }
2175         *pcur = rcur;
2176 
2177         xfs_rmap_ino_owner(&oinfo, owner, whichfork, startoff);
2178         unwritten = state == XFS_EXT_UNWRITTEN;
2179         bno = XFS_FSB_TO_AGBNO(rcur->bc_mp, startblock);
2180 
2181         switch (type) {
2182         case XFS_RMAP_ALLOC:
2183         case XFS_RMAP_MAP:
2184                 error = xfs_rmap_map(rcur, bno, blockcount, unwritten, &oinfo);
2185                 break;
2186         case XFS_RMAP_MAP_SHARED:
2187                 error = xfs_rmap_map_shared(rcur, bno, blockcount, unwritten,
2188                                 &oinfo);
2189                 break;
2190         case XFS_RMAP_FREE:
2191         case XFS_RMAP_UNMAP:
2192                 error = xfs_rmap_unmap(rcur, bno, blockcount, unwritten,
2193                                 &oinfo);
2194                 break;
2195         case XFS_RMAP_UNMAP_SHARED:
2196                 error = xfs_rmap_unmap_shared(rcur, bno, blockcount, unwritten,
2197                                 &oinfo);
2198                 break;
2199         case XFS_RMAP_CONVERT:
2200                 error = xfs_rmap_convert(rcur, bno, blockcount, !unwritten,
2201                                 &oinfo);
2202                 break;
2203         case XFS_RMAP_CONVERT_SHARED:
2204                 error = xfs_rmap_convert_shared(rcur, bno, blockcount,
2205                                 !unwritten, &oinfo);
2206                 break;
2207         default:
2208                 ASSERT(0);
2209                 error = -EFSCORRUPTED;
2210         }
2211         return error;
2212 
2213 out_cur:
2214         xfs_trans_brelse(tp, agbp);
2215 
2216         return error;
2217 }
2218 
2219 /*
2220  * Don't defer an rmap if we aren't an rmap filesystem.
2221  */
2222 static bool
2223 xfs_rmap_update_is_needed(
2224         struct xfs_mount        *mp,
2225         int                     whichfork)
2226 {
2227         return xfs_sb_version_hasrmapbt(&mp->m_sb) && whichfork != XFS_COW_FORK;
2228 }
2229 
2230 /*
2231  * Record a rmap intent; the list is kept sorted first by AG and then by
2232  * increasing age.
2233  */
2234 static int
2235 __xfs_rmap_add(
2236         struct xfs_mount                *mp,
2237         struct xfs_defer_ops            *dfops,
2238         enum xfs_rmap_intent_type       type,
2239         uint64_t                        owner,
2240         int                             whichfork,
2241         struct xfs_bmbt_irec            *bmap)
2242 {
2243         struct xfs_rmap_intent  *ri;
2244 
2245         trace_xfs_rmap_defer(mp, XFS_FSB_TO_AGNO(mp, bmap->br_startblock),
2246                         type,
2247                         XFS_FSB_TO_AGBNO(mp, bmap->br_startblock),
2248                         owner, whichfork,
2249                         bmap->br_startoff,
2250                         bmap->br_blockcount,
2251                         bmap->br_state);
2252 
2253         ri = kmem_alloc(sizeof(struct xfs_rmap_intent), KM_SLEEP | KM_NOFS);
2254         INIT_LIST_HEAD(&ri->ri_list);
2255         ri->ri_type = type;
2256         ri->ri_owner = owner;
2257         ri->ri_whichfork = whichfork;
2258         ri->ri_bmap = *bmap;
2259 
2260         xfs_defer_add(dfops, XFS_DEFER_OPS_TYPE_RMAP, &ri->ri_list);
2261         return 0;
2262 }
2263 
2264 /* Map an extent into a file. */
2265 int
2266 xfs_rmap_map_extent(
2267         struct xfs_mount        *mp,
2268         struct xfs_defer_ops    *dfops,
2269         struct xfs_inode        *ip,
2270         int                     whichfork,
2271         struct xfs_bmbt_irec    *PREV)
2272 {
2273         if (!xfs_rmap_update_is_needed(mp, whichfork))
2274                 return 0;
2275 
2276         return __xfs_rmap_add(mp, dfops, xfs_is_reflink_inode(ip) ?
2277                         XFS_RMAP_MAP_SHARED : XFS_RMAP_MAP, ip->i_ino,
2278                         whichfork, PREV);
2279 }
2280 
2281 /* Unmap an extent out of a file. */
2282 int
2283 xfs_rmap_unmap_extent(
2284         struct xfs_mount        *mp,
2285         struct xfs_defer_ops    *dfops,
2286         struct xfs_inode        *ip,
2287         int                     whichfork,
2288         struct xfs_bmbt_irec    *PREV)
2289 {
2290         if (!xfs_rmap_update_is_needed(mp, whichfork))
2291                 return 0;
2292 
2293         return __xfs_rmap_add(mp, dfops, xfs_is_reflink_inode(ip) ?
2294                         XFS_RMAP_UNMAP_SHARED : XFS_RMAP_UNMAP, ip->i_ino,
2295                         whichfork, PREV);
2296 }
2297 
2298 /* Convert a data fork extent from unwritten to real or vice versa. */
2299 int
2300 xfs_rmap_convert_extent(
2301         struct xfs_mount        *mp,
2302         struct xfs_defer_ops    *dfops,
2303         struct xfs_inode        *ip,
2304         int                     whichfork,
2305         struct xfs_bmbt_irec    *PREV)
2306 {
2307         if (!xfs_rmap_update_is_needed(mp, whichfork))
2308                 return 0;
2309 
2310         return __xfs_rmap_add(mp, dfops, xfs_is_reflink_inode(ip) ?
2311                         XFS_RMAP_CONVERT_SHARED : XFS_RMAP_CONVERT, ip->i_ino,
2312                         whichfork, PREV);
2313 }
2314 
2315 /* Schedule the creation of an rmap for non-file data. */
2316 int
2317 xfs_rmap_alloc_extent(
2318         struct xfs_mount        *mp,
2319         struct xfs_defer_ops    *dfops,
2320         xfs_agnumber_t          agno,
2321         xfs_agblock_t           bno,
2322         xfs_extlen_t            len,
2323         uint64_t                owner)
2324 {
2325         struct xfs_bmbt_irec    bmap;
2326 
2327         if (!xfs_rmap_update_is_needed(mp, XFS_DATA_FORK))
2328                 return 0;
2329 
2330         bmap.br_startblock = XFS_AGB_TO_FSB(mp, agno, bno);
2331         bmap.br_blockcount = len;
2332         bmap.br_startoff = 0;
2333         bmap.br_state = XFS_EXT_NORM;
2334 
2335         return __xfs_rmap_add(mp, dfops, XFS_RMAP_ALLOC, owner,
2336                         XFS_DATA_FORK, &bmap);
2337 }
2338 
2339 /* Schedule the deletion of an rmap for non-file data. */
2340 int
2341 xfs_rmap_free_extent(
2342         struct xfs_mount        *mp,
2343         struct xfs_defer_ops    *dfops,
2344         xfs_agnumber_t          agno,
2345         xfs_agblock_t           bno,
2346         xfs_extlen_t            len,
2347         uint64_t                owner)
2348 {
2349         struct xfs_bmbt_irec    bmap;
2350 
2351         if (!xfs_rmap_update_is_needed(mp, XFS_DATA_FORK))
2352                 return 0;
2353 
2354         bmap.br_startblock = XFS_AGB_TO_FSB(mp, agno, bno);
2355         bmap.br_blockcount = len;
2356         bmap.br_startoff = 0;
2357         bmap.br_state = XFS_EXT_NORM;
2358 
2359         return __xfs_rmap_add(mp, dfops, XFS_RMAP_FREE, owner,
2360                         XFS_DATA_FORK, &bmap);
2361 }
2362 
2363 /* Compare rmap records.  Returns -1 if a < b, 1 if a > b, and 0 if equal. */
2364 int
2365 xfs_rmap_compare(
2366         const struct xfs_rmap_irec      *a,
2367         const struct xfs_rmap_irec      *b)
2368 {
2369         __u64                           oa;
2370         __u64                           ob;
2371 
2372         oa = xfs_rmap_irec_offset_pack(a);
2373         ob = xfs_rmap_irec_offset_pack(b);
2374 
2375         if (a->rm_startblock < b->rm_startblock)
2376                 return -1;
2377         else if (a->rm_startblock > b->rm_startblock)
2378                 return 1;
2379         else if (a->rm_owner < b->rm_owner)
2380                 return -1;
2381         else if (a->rm_owner > b->rm_owner)
2382                 return 1;
2383         else if (oa < ob)
2384                 return -1;
2385         else if (oa > ob)
2386                 return 1;
2387         else
2388                 return 0;
2389 }
2390 
2391 /* Is there a record covering a given extent? */
2392 int
2393 xfs_rmap_has_record(
2394         struct xfs_btree_cur    *cur,
2395         xfs_agblock_t           bno,
2396         xfs_extlen_t            len,
2397         bool                    *exists)
2398 {
2399         union xfs_btree_irec    low;
2400         union xfs_btree_irec    high;
2401 
2402         memset(&low, 0, sizeof(low));
2403         low.r.rm_startblock = bno;
2404         memset(&high, 0xFF, sizeof(high));
2405         high.r.rm_startblock = bno + len - 1;
2406 
2407         return xfs_btree_has_record(cur, &low, &high, exists);
2408 }
2409 
2410 /*
2411  * Is there a record for this owner completely covering a given physical
2412  * extent?  If so, *has_rmap will be set to true.  If there is no record
2413  * or the record only covers part of the range, we set *has_rmap to false.
2414  * This function doesn't perform range lookups or offset checks, so it is
2415  * not suitable for checking data fork blocks.
2416  */
2417 int
2418 xfs_rmap_record_exists(
2419         struct xfs_btree_cur    *cur,
2420         xfs_agblock_t           bno,
2421         xfs_extlen_t            len,
2422         struct xfs_owner_info   *oinfo,
2423         bool                    *has_rmap)
2424 {
2425         uint64_t                owner;
2426         uint64_t                offset;
2427         unsigned int            flags;
2428         int                     has_record;
2429         struct xfs_rmap_irec    irec;
2430         int                     error;
2431 
2432         xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
2433         ASSERT(XFS_RMAP_NON_INODE_OWNER(owner) ||
2434                (flags & XFS_RMAP_BMBT_BLOCK));
2435 
2436         error = xfs_rmap_lookup_le(cur, bno, len, owner, offset, flags,
2437                         &has_record);
2438         if (error)
2439                 return error;
2440         if (!has_record) {
2441                 *has_rmap = false;
2442                 return 0;
2443         }
2444 
2445         error = xfs_rmap_get_rec(cur, &irec, &has_record);
2446         if (error)
2447                 return error;
2448         if (!has_record) {
2449                 *has_rmap = false;
2450                 return 0;
2451         }
2452 
2453         *has_rmap = (irec.rm_owner == owner && irec.rm_startblock <= bno &&
2454                      irec.rm_startblock + irec.rm_blockcount >= bno + len);
2455         return 0;
2456 }
2457 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

osdn.jp