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

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

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ 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.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 // SPDX-License-Identifier: GPL-2.0
  2 /*
  3  * Copyright (c) 2014 Red Hat, Inc.
  4  * All Rights Reserved.
  5  */
  6 #include "xfs.h"
  7 #include "xfs_fs.h"
  8 #include "xfs_shared.h"
  9 #include "xfs_format.h"
 10 #include "xfs_log_format.h"
 11 #include "xfs_trans_resv.h"
 12 #include "xfs_bit.h"
 13 #include "xfs_mount.h"
 14 #include "xfs_sb.h"
 15 #include "xfs_defer.h"
 16 #include "xfs_btree.h"
 17 #include "xfs_trans.h"
 18 #include "xfs_alloc.h"
 19 #include "xfs_rmap.h"
 20 #include "xfs_rmap_btree.h"
 21 #include "xfs_trace.h"
 22 #include "xfs_errortag.h"
 23 #include "xfs_error.h"
 24 #include "xfs_inode.h"
 25 #include "xfs_ag.h"
 26 #include "xfs_health.h"
 27 #include "xfs_rmap_item.h"
 28 
 29 struct kmem_cache       *xfs_rmap_intent_cache;
 30 
 31 /*
 32  * Lookup the first record less than or equal to [bno, len, owner, offset]
 33  * in the btree given by cur.
 34  */
 35 int
 36 xfs_rmap_lookup_le(
 37         struct xfs_btree_cur    *cur,
 38         xfs_agblock_t           bno,
 39         uint64_t                owner,
 40         uint64_t                offset,
 41         unsigned int            flags,
 42         struct xfs_rmap_irec    *irec,
 43         int                     *stat)
 44 {
 45         int                     get_stat = 0;
 46         int                     error;
 47 
 48         cur->bc_rec.r.rm_startblock = bno;
 49         cur->bc_rec.r.rm_blockcount = 0;
 50         cur->bc_rec.r.rm_owner = owner;
 51         cur->bc_rec.r.rm_offset = offset;
 52         cur->bc_rec.r.rm_flags = flags;
 53 
 54         error = xfs_btree_lookup(cur, XFS_LOOKUP_LE, stat);
 55         if (error || !(*stat) || !irec)
 56                 return error;
 57 
 58         error = xfs_rmap_get_rec(cur, irec, &get_stat);
 59         if (error)
 60                 return error;
 61         if (!get_stat) {
 62                 xfs_btree_mark_sick(cur);
 63                 return -EFSCORRUPTED;
 64         }
 65 
 66         return 0;
 67 }
 68 
 69 /*
 70  * Lookup the record exactly matching [bno, len, owner, offset]
 71  * in the btree given by cur.
 72  */
 73 int
 74 xfs_rmap_lookup_eq(
 75         struct xfs_btree_cur    *cur,
 76         xfs_agblock_t           bno,
 77         xfs_extlen_t            len,
 78         uint64_t                owner,
 79         uint64_t                offset,
 80         unsigned int            flags,
 81         int                     *stat)
 82 {
 83         cur->bc_rec.r.rm_startblock = bno;
 84         cur->bc_rec.r.rm_blockcount = len;
 85         cur->bc_rec.r.rm_owner = owner;
 86         cur->bc_rec.r.rm_offset = offset;
 87         cur->bc_rec.r.rm_flags = flags;
 88         return xfs_btree_lookup(cur, XFS_LOOKUP_EQ, stat);
 89 }
 90 
 91 /*
 92  * Update the record referred to by cur to the value given
 93  * by [bno, len, owner, offset].
 94  * This either works (return 0) or gets an EFSCORRUPTED error.
 95  */
 96 STATIC int
 97 xfs_rmap_update(
 98         struct xfs_btree_cur    *cur,
 99         struct xfs_rmap_irec    *irec)
100 {
101         union xfs_btree_rec     rec;
102         int                     error;
103 
104         trace_xfs_rmap_update(cur, irec->rm_startblock, irec->rm_blockcount,
105                         irec->rm_owner, irec->rm_offset, irec->rm_flags);
106 
107         rec.rmap.rm_startblock = cpu_to_be32(irec->rm_startblock);
108         rec.rmap.rm_blockcount = cpu_to_be32(irec->rm_blockcount);
109         rec.rmap.rm_owner = cpu_to_be64(irec->rm_owner);
110         rec.rmap.rm_offset = cpu_to_be64(
111                         xfs_rmap_irec_offset_pack(irec));
112         error = xfs_btree_update(cur, &rec);
113         if (error)
114                 trace_xfs_rmap_update_error(cur, error, _RET_IP_);
115         return error;
116 }
117 
118 int
119 xfs_rmap_insert(
120         struct xfs_btree_cur    *rcur,
121         xfs_agblock_t           agbno,
122         xfs_extlen_t            len,
123         uint64_t                owner,
124         uint64_t                offset,
125         unsigned int            flags)
126 {
127         int                     i;
128         int                     error;
129 
130         trace_xfs_rmap_insert(rcur, agbno, len, owner, offset, flags);
131 
132         error = xfs_rmap_lookup_eq(rcur, agbno, len, owner, offset, flags, &i);
133         if (error)
134                 goto done;
135         if (XFS_IS_CORRUPT(rcur->bc_mp, i != 0)) {
136                 xfs_btree_mark_sick(rcur);
137                 error = -EFSCORRUPTED;
138                 goto done;
139         }
140 
141         rcur->bc_rec.r.rm_startblock = agbno;
142         rcur->bc_rec.r.rm_blockcount = len;
143         rcur->bc_rec.r.rm_owner = owner;
144         rcur->bc_rec.r.rm_offset = offset;
145         rcur->bc_rec.r.rm_flags = flags;
146         error = xfs_btree_insert(rcur, &i);
147         if (error)
148                 goto done;
149         if (XFS_IS_CORRUPT(rcur->bc_mp, i != 1)) {
150                 xfs_btree_mark_sick(rcur);
151                 error = -EFSCORRUPTED;
152                 goto done;
153         }
154 done:
155         if (error)
156                 trace_xfs_rmap_insert_error(rcur, error, _RET_IP_);
157         return error;
158 }
159 
160 STATIC int
161 xfs_rmap_delete(
162         struct xfs_btree_cur    *rcur,
163         xfs_agblock_t           agbno,
164         xfs_extlen_t            len,
165         uint64_t                owner,
166         uint64_t                offset,
167         unsigned int            flags)
168 {
169         int                     i;
170         int                     error;
171 
172         trace_xfs_rmap_delete(rcur, agbno, len, owner, offset, flags);
173 
174         error = xfs_rmap_lookup_eq(rcur, agbno, len, owner, offset, flags, &i);
175         if (error)
176                 goto done;
177         if (XFS_IS_CORRUPT(rcur->bc_mp, i != 1)) {
178                 xfs_btree_mark_sick(rcur);
179                 error = -EFSCORRUPTED;
180                 goto done;
181         }
182 
183         error = xfs_btree_delete(rcur, &i);
184         if (error)
185                 goto done;
186         if (XFS_IS_CORRUPT(rcur->bc_mp, i != 1)) {
187                 xfs_btree_mark_sick(rcur);
188                 error = -EFSCORRUPTED;
189                 goto done;
190         }
191 done:
192         if (error)
193                 trace_xfs_rmap_delete_error(rcur, error, _RET_IP_);
194         return error;
195 }
196 
197 /* Convert an internal btree record to an rmap record. */
198 xfs_failaddr_t
199 xfs_rmap_btrec_to_irec(
200         const union xfs_btree_rec       *rec,
201         struct xfs_rmap_irec            *irec)
202 {
203         irec->rm_startblock = be32_to_cpu(rec->rmap.rm_startblock);
204         irec->rm_blockcount = be32_to_cpu(rec->rmap.rm_blockcount);
205         irec->rm_owner = be64_to_cpu(rec->rmap.rm_owner);
206         return xfs_rmap_irec_offset_unpack(be64_to_cpu(rec->rmap.rm_offset),
207                         irec);
208 }
209 
210 /* Simple checks for rmap records. */
211 xfs_failaddr_t
212 xfs_rmap_check_irec(
213         struct xfs_perag                *pag,
214         const struct xfs_rmap_irec      *irec)
215 {
216         struct xfs_mount                *mp = pag->pag_mount;
217         bool                            is_inode;
218         bool                            is_unwritten;
219         bool                            is_bmbt;
220         bool                            is_attr;
221 
222         if (irec->rm_blockcount == 0)
223                 return __this_address;
224         if (irec->rm_startblock <= XFS_AGFL_BLOCK(mp)) {
225                 if (irec->rm_owner != XFS_RMAP_OWN_FS)
226                         return __this_address;
227                 if (irec->rm_blockcount != XFS_AGFL_BLOCK(mp) + 1)
228                         return __this_address;
229         } else {
230                 /* check for valid extent range, including overflow */
231                 if (!xfs_verify_agbext(pag, irec->rm_startblock,
232                                             irec->rm_blockcount))
233                         return __this_address;
234         }
235 
236         if (!(xfs_verify_ino(mp, irec->rm_owner) ||
237               (irec->rm_owner <= XFS_RMAP_OWN_FS &&
238                irec->rm_owner >= XFS_RMAP_OWN_MIN)))
239                 return __this_address;
240 
241         /* Check flags. */
242         is_inode = !XFS_RMAP_NON_INODE_OWNER(irec->rm_owner);
243         is_bmbt = irec->rm_flags & XFS_RMAP_BMBT_BLOCK;
244         is_attr = irec->rm_flags & XFS_RMAP_ATTR_FORK;
245         is_unwritten = irec->rm_flags & XFS_RMAP_UNWRITTEN;
246 
247         if (is_bmbt && irec->rm_offset != 0)
248                 return __this_address;
249 
250         if (!is_inode && irec->rm_offset != 0)
251                 return __this_address;
252 
253         if (is_unwritten && (is_bmbt || !is_inode || is_attr))
254                 return __this_address;
255 
256         if (!is_inode && (is_bmbt || is_unwritten || is_attr))
257                 return __this_address;
258 
259         /* Check for a valid fork offset, if applicable. */
260         if (is_inode && !is_bmbt &&
261             !xfs_verify_fileext(mp, irec->rm_offset, irec->rm_blockcount))
262                 return __this_address;
263 
264         return NULL;
265 }
266 
267 static inline xfs_failaddr_t
268 xfs_rmap_check_btrec(
269         struct xfs_btree_cur            *cur,
270         const struct xfs_rmap_irec      *irec)
271 {
272         if (xfs_btree_is_mem_rmap(cur->bc_ops))
273                 return xfs_rmap_check_irec(cur->bc_mem.pag, irec);
274         return xfs_rmap_check_irec(cur->bc_ag.pag, irec);
275 }
276 
277 static inline int
278 xfs_rmap_complain_bad_rec(
279         struct xfs_btree_cur            *cur,
280         xfs_failaddr_t                  fa,
281         const struct xfs_rmap_irec      *irec)
282 {
283         struct xfs_mount                *mp = cur->bc_mp;
284 
285         if (xfs_btree_is_mem_rmap(cur->bc_ops))
286                 xfs_warn(mp,
287  "In-Memory Reverse Mapping BTree record corruption detected at %pS!", fa);
288         else
289                 xfs_warn(mp,
290  "Reverse Mapping BTree record corruption in AG %d detected at %pS!",
291                         cur->bc_ag.pag->pag_agno, fa);
292         xfs_warn(mp,
293                 "Owner 0x%llx, flags 0x%x, start block 0x%x block count 0x%x",
294                 irec->rm_owner, irec->rm_flags, irec->rm_startblock,
295                 irec->rm_blockcount);
296         xfs_btree_mark_sick(cur);
297         return -EFSCORRUPTED;
298 }
299 
300 /*
301  * Get the data from the pointed-to record.
302  */
303 int
304 xfs_rmap_get_rec(
305         struct xfs_btree_cur    *cur,
306         struct xfs_rmap_irec    *irec,
307         int                     *stat)
308 {
309         union xfs_btree_rec     *rec;
310         xfs_failaddr_t          fa;
311         int                     error;
312 
313         error = xfs_btree_get_rec(cur, &rec, stat);
314         if (error || !*stat)
315                 return error;
316 
317         fa = xfs_rmap_btrec_to_irec(rec, irec);
318         if (!fa)
319                 fa = xfs_rmap_check_btrec(cur, irec);
320         if (fa)
321                 return xfs_rmap_complain_bad_rec(cur, fa, irec);
322 
323         return 0;
324 }
325 
326 struct xfs_find_left_neighbor_info {
327         struct xfs_rmap_irec    high;
328         struct xfs_rmap_irec    *irec;
329 };
330 
331 /* For each rmap given, figure out if it matches the key we want. */
332 STATIC int
333 xfs_rmap_find_left_neighbor_helper(
334         struct xfs_btree_cur            *cur,
335         const struct xfs_rmap_irec      *rec,
336         void                            *priv)
337 {
338         struct xfs_find_left_neighbor_info      *info = priv;
339 
340         trace_xfs_rmap_find_left_neighbor_candidate(cur, rec->rm_startblock,
341                         rec->rm_blockcount, rec->rm_owner, rec->rm_offset,
342                         rec->rm_flags);
343 
344         if (rec->rm_owner != info->high.rm_owner)
345                 return 0;
346         if (!XFS_RMAP_NON_INODE_OWNER(rec->rm_owner) &&
347             !(rec->rm_flags & XFS_RMAP_BMBT_BLOCK) &&
348             rec->rm_offset + rec->rm_blockcount - 1 != info->high.rm_offset)
349                 return 0;
350 
351         *info->irec = *rec;
352         return -ECANCELED;
353 }
354 
355 /*
356  * Find the record to the left of the given extent, being careful only to
357  * return a match with the same owner and adjacent physical and logical
358  * block ranges.
359  */
360 STATIC int
361 xfs_rmap_find_left_neighbor(
362         struct xfs_btree_cur    *cur,
363         xfs_agblock_t           bno,
364         uint64_t                owner,
365         uint64_t                offset,
366         unsigned int            flags,
367         struct xfs_rmap_irec    *irec,
368         int                     *stat)
369 {
370         struct xfs_find_left_neighbor_info      info;
371         int                     found = 0;
372         int                     error;
373 
374         *stat = 0;
375         if (bno == 0)
376                 return 0;
377         info.high.rm_startblock = bno - 1;
378         info.high.rm_owner = owner;
379         if (!XFS_RMAP_NON_INODE_OWNER(owner) &&
380             !(flags & XFS_RMAP_BMBT_BLOCK)) {
381                 if (offset == 0)
382                         return 0;
383                 info.high.rm_offset = offset - 1;
384         } else
385                 info.high.rm_offset = 0;
386         info.high.rm_flags = flags;
387         info.high.rm_blockcount = 0;
388         info.irec = irec;
389 
390         trace_xfs_rmap_find_left_neighbor_query(cur, bno, 0, owner, offset,
391                         flags);
392 
393         /*
394          * Historically, we always used the range query to walk every reverse
395          * mapping that could possibly overlap the key that the caller asked
396          * for, and filter out the ones that don't.  That is very slow when
397          * there are a lot of records.
398          *
399          * However, there are two scenarios where the classic btree search can
400          * produce correct results -- if the index contains a record that is an
401          * exact match for the lookup key; and if there are no other records
402          * between the record we want and the key we supplied.
403          *
404          * As an optimization, try a non-overlapped lookup first.  This makes
405          * extent conversion and remap operations run a bit faster if the
406          * physical extents aren't being shared.  If we don't find what we
407          * want, we fall back to the overlapped query.
408          */
409         error = xfs_rmap_lookup_le(cur, bno, owner, offset, flags, irec,
410                         &found);
411         if (error)
412                 return error;
413         if (found)
414                 error = xfs_rmap_find_left_neighbor_helper(cur, irec, &info);
415         if (!error)
416                 error = xfs_rmap_query_range(cur, &info.high, &info.high,
417                                 xfs_rmap_find_left_neighbor_helper, &info);
418         if (error != -ECANCELED)
419                 return error;
420 
421         *stat = 1;
422         trace_xfs_rmap_find_left_neighbor_result(cur, irec->rm_startblock,
423                         irec->rm_blockcount, irec->rm_owner, irec->rm_offset,
424                         irec->rm_flags);
425         return 0;
426 }
427 
428 /* For each rmap given, figure out if it matches the key we want. */
429 STATIC int
430 xfs_rmap_lookup_le_range_helper(
431         struct xfs_btree_cur            *cur,
432         const struct xfs_rmap_irec      *rec,
433         void                            *priv)
434 {
435         struct xfs_find_left_neighbor_info      *info = priv;
436 
437         trace_xfs_rmap_lookup_le_range_candidate(cur, rec->rm_startblock,
438                         rec->rm_blockcount, rec->rm_owner, rec->rm_offset,
439                         rec->rm_flags);
440 
441         if (rec->rm_owner != info->high.rm_owner)
442                 return 0;
443         if (!XFS_RMAP_NON_INODE_OWNER(rec->rm_owner) &&
444             !(rec->rm_flags & XFS_RMAP_BMBT_BLOCK) &&
445             (rec->rm_offset > info->high.rm_offset ||
446              rec->rm_offset + rec->rm_blockcount <= info->high.rm_offset))
447                 return 0;
448 
449         *info->irec = *rec;
450         return -ECANCELED;
451 }
452 
453 /*
454  * Find the record to the left of the given extent, being careful only to
455  * return a match with the same owner and overlapping physical and logical
456  * block ranges.  This is the overlapping-interval version of
457  * xfs_rmap_lookup_le.
458  */
459 int
460 xfs_rmap_lookup_le_range(
461         struct xfs_btree_cur    *cur,
462         xfs_agblock_t           bno,
463         uint64_t                owner,
464         uint64_t                offset,
465         unsigned int            flags,
466         struct xfs_rmap_irec    *irec,
467         int                     *stat)
468 {
469         struct xfs_find_left_neighbor_info      info;
470         int                     found = 0;
471         int                     error;
472 
473         info.high.rm_startblock = bno;
474         info.high.rm_owner = owner;
475         if (!XFS_RMAP_NON_INODE_OWNER(owner) && !(flags & XFS_RMAP_BMBT_BLOCK))
476                 info.high.rm_offset = offset;
477         else
478                 info.high.rm_offset = 0;
479         info.high.rm_flags = flags;
480         info.high.rm_blockcount = 0;
481         *stat = 0;
482         info.irec = irec;
483 
484         trace_xfs_rmap_lookup_le_range(cur, bno, 0, owner, offset, flags);
485 
486         /*
487          * Historically, we always used the range query to walk every reverse
488          * mapping that could possibly overlap the key that the caller asked
489          * for, and filter out the ones that don't.  That is very slow when
490          * there are a lot of records.
491          *
492          * However, there are two scenarios where the classic btree search can
493          * produce correct results -- if the index contains a record that is an
494          * exact match for the lookup key; and if there are no other records
495          * between the record we want and the key we supplied.
496          *
497          * As an optimization, try a non-overlapped lookup first.  This makes
498          * scrub run much faster on most filesystems because bmbt records are
499          * usually an exact match for rmap records.  If we don't find what we
500          * want, we fall back to the overlapped query.
501          */
502         error = xfs_rmap_lookup_le(cur, bno, owner, offset, flags, irec,
503                         &found);
504         if (error)
505                 return error;
506         if (found)
507                 error = xfs_rmap_lookup_le_range_helper(cur, irec, &info);
508         if (!error)
509                 error = xfs_rmap_query_range(cur, &info.high, &info.high,
510                                 xfs_rmap_lookup_le_range_helper, &info);
511         if (error != -ECANCELED)
512                 return error;
513 
514         *stat = 1;
515         trace_xfs_rmap_lookup_le_range_result(cur, irec->rm_startblock,
516                         irec->rm_blockcount, irec->rm_owner, irec->rm_offset,
517                         irec->rm_flags);
518         return 0;
519 }
520 
521 /*
522  * Perform all the relevant owner checks for a removal op.  If we're doing an
523  * unknown-owner removal then we have no owner information to check.
524  */
525 static int
526 xfs_rmap_free_check_owner(
527         struct xfs_btree_cur    *cur,
528         uint64_t                ltoff,
529         struct xfs_rmap_irec    *rec,
530         xfs_filblks_t           len,
531         uint64_t                owner,
532         uint64_t                offset,
533         unsigned int            flags)
534 {
535         struct xfs_mount        *mp = cur->bc_mp;
536         int                     error = 0;
537 
538         if (owner == XFS_RMAP_OWN_UNKNOWN)
539                 return 0;
540 
541         /* Make sure the unwritten flag matches. */
542         if (XFS_IS_CORRUPT(mp,
543                            (flags & XFS_RMAP_UNWRITTEN) !=
544                            (rec->rm_flags & XFS_RMAP_UNWRITTEN))) {
545                 xfs_btree_mark_sick(cur);
546                 error = -EFSCORRUPTED;
547                 goto out;
548         }
549 
550         /* Make sure the owner matches what we expect to find in the tree. */
551         if (XFS_IS_CORRUPT(mp, owner != rec->rm_owner)) {
552                 xfs_btree_mark_sick(cur);
553                 error = -EFSCORRUPTED;
554                 goto out;
555         }
556 
557         /* Check the offset, if necessary. */
558         if (XFS_RMAP_NON_INODE_OWNER(owner))
559                 goto out;
560 
561         if (flags & XFS_RMAP_BMBT_BLOCK) {
562                 if (XFS_IS_CORRUPT(mp,
563                                    !(rec->rm_flags & XFS_RMAP_BMBT_BLOCK))) {
564                         xfs_btree_mark_sick(cur);
565                         error = -EFSCORRUPTED;
566                         goto out;
567                 }
568         } else {
569                 if (XFS_IS_CORRUPT(mp, rec->rm_offset > offset)) {
570                         xfs_btree_mark_sick(cur);
571                         error = -EFSCORRUPTED;
572                         goto out;
573                 }
574                 if (XFS_IS_CORRUPT(mp,
575                                    offset + len > ltoff + rec->rm_blockcount)) {
576                         xfs_btree_mark_sick(cur);
577                         error = -EFSCORRUPTED;
578                         goto out;
579                 }
580         }
581 
582 out:
583         return error;
584 }
585 
586 /*
587  * Find the extent in the rmap btree and remove it.
588  *
589  * The record we find should always be an exact match for the extent that we're
590  * looking for, since we insert them into the btree without modification.
591  *
592  * Special Case #1: when growing the filesystem, we "free" an extent when
593  * growing the last AG. This extent is new space and so it is not tracked as
594  * used space in the btree. The growfs code will pass in an owner of
595  * XFS_RMAP_OWN_NULL to indicate that it expected that there is no owner of this
596  * extent. We verify that - the extent lookup result in a record that does not
597  * overlap.
598  *
599  * Special Case #2: EFIs do not record the owner of the extent, so when
600  * recovering EFIs from the log we pass in XFS_RMAP_OWN_UNKNOWN to tell the rmap
601  * btree to ignore the owner (i.e. wildcard match) so we don't trigger
602  * corruption checks during log recovery.
603  */
604 STATIC int
605 xfs_rmap_unmap(
606         struct xfs_btree_cur            *cur,
607         xfs_agblock_t                   bno,
608         xfs_extlen_t                    len,
609         bool                            unwritten,
610         const struct xfs_owner_info     *oinfo)
611 {
612         struct xfs_mount                *mp = cur->bc_mp;
613         struct xfs_rmap_irec            ltrec;
614         uint64_t                        ltoff;
615         int                             error = 0;
616         int                             i;
617         uint64_t                        owner;
618         uint64_t                        offset;
619         unsigned int                    flags;
620         bool                            ignore_off;
621 
622         xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
623         ignore_off = XFS_RMAP_NON_INODE_OWNER(owner) ||
624                         (flags & XFS_RMAP_BMBT_BLOCK);
625         if (unwritten)
626                 flags |= XFS_RMAP_UNWRITTEN;
627         trace_xfs_rmap_unmap(cur, bno, len, unwritten, oinfo);
628 
629         /*
630          * We should always have a left record because there's a static record
631          * for the AG headers at rm_startblock == 0 created by mkfs/growfs that
632          * will not ever be removed from the tree.
633          */
634         error = xfs_rmap_lookup_le(cur, bno, owner, offset, flags, &ltrec, &i);
635         if (error)
636                 goto out_error;
637         if (XFS_IS_CORRUPT(mp, i != 1)) {
638                 xfs_btree_mark_sick(cur);
639                 error = -EFSCORRUPTED;
640                 goto out_error;
641         }
642 
643         trace_xfs_rmap_lookup_le_range_result(cur, ltrec.rm_startblock,
644                         ltrec.rm_blockcount, ltrec.rm_owner, ltrec.rm_offset,
645                         ltrec.rm_flags);
646         ltoff = ltrec.rm_offset;
647 
648         /*
649          * For growfs, the incoming extent must be beyond the left record we
650          * just found as it is new space and won't be used by anyone. This is
651          * just a corruption check as we don't actually do anything with this
652          * extent.  Note that we need to use >= instead of > because it might
653          * be the case that the "left" extent goes all the way to EOFS.
654          */
655         if (owner == XFS_RMAP_OWN_NULL) {
656                 if (XFS_IS_CORRUPT(mp,
657                                    bno <
658                                    ltrec.rm_startblock + ltrec.rm_blockcount)) {
659                         xfs_btree_mark_sick(cur);
660                         error = -EFSCORRUPTED;
661                         goto out_error;
662                 }
663                 goto out_done;
664         }
665 
666         /*
667          * If we're doing an unknown-owner removal for EFI recovery, we expect
668          * to find the full range in the rmapbt or nothing at all.  If we
669          * don't find any rmaps overlapping either end of the range, we're
670          * done.  Hopefully this means that the EFI creator already queued
671          * (and finished) a RUI to remove the rmap.
672          */
673         if (owner == XFS_RMAP_OWN_UNKNOWN &&
674             ltrec.rm_startblock + ltrec.rm_blockcount <= bno) {
675                 struct xfs_rmap_irec    rtrec;
676 
677                 error = xfs_btree_increment(cur, 0, &i);
678                 if (error)
679                         goto out_error;
680                 if (i == 0)
681                         goto out_done;
682                 error = xfs_rmap_get_rec(cur, &rtrec, &i);
683                 if (error)
684                         goto out_error;
685                 if (XFS_IS_CORRUPT(mp, i != 1)) {
686                         xfs_btree_mark_sick(cur);
687                         error = -EFSCORRUPTED;
688                         goto out_error;
689                 }
690                 if (rtrec.rm_startblock >= bno + len)
691                         goto out_done;
692         }
693 
694         /* Make sure the extent we found covers the entire freeing range. */
695         if (XFS_IS_CORRUPT(mp,
696                            ltrec.rm_startblock > bno ||
697                            ltrec.rm_startblock + ltrec.rm_blockcount <
698                            bno + len)) {
699                 xfs_btree_mark_sick(cur);
700                 error = -EFSCORRUPTED;
701                 goto out_error;
702         }
703 
704         /* Check owner information. */
705         error = xfs_rmap_free_check_owner(cur, ltoff, &ltrec, len, owner,
706                         offset, flags);
707         if (error)
708                 goto out_error;
709 
710         if (ltrec.rm_startblock == bno && ltrec.rm_blockcount == len) {
711                 /* exact match, simply remove the record from rmap tree */
712                 trace_xfs_rmap_delete(cur, ltrec.rm_startblock,
713                                 ltrec.rm_blockcount, ltrec.rm_owner,
714                                 ltrec.rm_offset, ltrec.rm_flags);
715                 error = xfs_btree_delete(cur, &i);
716                 if (error)
717                         goto out_error;
718                 if (XFS_IS_CORRUPT(mp, i != 1)) {
719                         xfs_btree_mark_sick(cur);
720                         error = -EFSCORRUPTED;
721                         goto out_error;
722                 }
723         } else if (ltrec.rm_startblock == bno) {
724                 /*
725                  * overlap left hand side of extent: move the start, trim the
726                  * length and update the current record.
727                  *
728                  *       ltbno                ltlen
729                  * Orig:    |oooooooooooooooooooo|
730                  * Freeing: |fffffffff|
731                  * Result:            |rrrrrrrrrr|
732                  *         bno       len
733                  */
734                 ltrec.rm_startblock += len;
735                 ltrec.rm_blockcount -= len;
736                 if (!ignore_off)
737                         ltrec.rm_offset += len;
738                 error = xfs_rmap_update(cur, &ltrec);
739                 if (error)
740                         goto out_error;
741         } else if (ltrec.rm_startblock + ltrec.rm_blockcount == bno + len) {
742                 /*
743                  * overlap right hand side of extent: trim the length and update
744                  * the current record.
745                  *
746                  *       ltbno                ltlen
747                  * Orig:    |oooooooooooooooooooo|
748                  * Freeing:            |fffffffff|
749                  * Result:  |rrrrrrrrrr|
750                  *                    bno       len
751                  */
752                 ltrec.rm_blockcount -= len;
753                 error = xfs_rmap_update(cur, &ltrec);
754                 if (error)
755                         goto out_error;
756         } else {
757 
758                 /*
759                  * overlap middle of extent: trim the length of the existing
760                  * record to the length of the new left-extent size, increment
761                  * the insertion position so we can insert a new record
762                  * containing the remaining right-extent space.
763                  *
764                  *       ltbno                ltlen
765                  * Orig:    |oooooooooooooooooooo|
766                  * Freeing:       |fffffffff|
767                  * Result:  |rrrrr|         |rrrr|
768                  *               bno       len
769                  */
770                 xfs_extlen_t    orig_len = ltrec.rm_blockcount;
771 
772                 ltrec.rm_blockcount = bno - ltrec.rm_startblock;
773                 error = xfs_rmap_update(cur, &ltrec);
774                 if (error)
775                         goto out_error;
776 
777                 error = xfs_btree_increment(cur, 0, &i);
778                 if (error)
779                         goto out_error;
780 
781                 cur->bc_rec.r.rm_startblock = bno + len;
782                 cur->bc_rec.r.rm_blockcount = orig_len - len -
783                                                      ltrec.rm_blockcount;
784                 cur->bc_rec.r.rm_owner = ltrec.rm_owner;
785                 if (ignore_off)
786                         cur->bc_rec.r.rm_offset = 0;
787                 else
788                         cur->bc_rec.r.rm_offset = offset + len;
789                 cur->bc_rec.r.rm_flags = flags;
790                 trace_xfs_rmap_insert(cur, cur->bc_rec.r.rm_startblock,
791                                 cur->bc_rec.r.rm_blockcount,
792                                 cur->bc_rec.r.rm_owner,
793                                 cur->bc_rec.r.rm_offset,
794                                 cur->bc_rec.r.rm_flags);
795                 error = xfs_btree_insert(cur, &i);
796                 if (error)
797                         goto out_error;
798         }
799 
800 out_done:
801         trace_xfs_rmap_unmap_done(cur, bno, len, unwritten, oinfo);
802 out_error:
803         if (error)
804                 trace_xfs_rmap_unmap_error(cur, error, _RET_IP_);
805         return error;
806 }
807 
808 #ifdef CONFIG_XFS_LIVE_HOOKS
809 /*
810  * Use a static key here to reduce the overhead of rmapbt live updates.  If
811  * the compiler supports jump labels, the static branch will be replaced by a
812  * nop sled when there are no hook users.  Online fsck is currently the only
813  * caller, so this is a reasonable tradeoff.
814  *
815  * Note: Patching the kernel code requires taking the cpu hotplug lock.  Other
816  * parts of the kernel allocate memory with that lock held, which means that
817  * XFS callers cannot hold any locks that might be used by memory reclaim or
818  * writeback when calling the static_branch_{inc,dec} functions.
819  */
820 DEFINE_STATIC_XFS_HOOK_SWITCH(xfs_rmap_hooks_switch);
821 
822 void
823 xfs_rmap_hook_disable(void)
824 {
825         xfs_hooks_switch_off(&xfs_rmap_hooks_switch);
826 }
827 
828 void
829 xfs_rmap_hook_enable(void)
830 {
831         xfs_hooks_switch_on(&xfs_rmap_hooks_switch);
832 }
833 
834 /* Call downstream hooks for a reverse mapping update. */
835 static inline void
836 xfs_rmap_update_hook(
837         struct xfs_trans                *tp,
838         struct xfs_perag                *pag,
839         enum xfs_rmap_intent_type       op,
840         xfs_agblock_t                   startblock,
841         xfs_extlen_t                    blockcount,
842         bool                            unwritten,
843         const struct xfs_owner_info     *oinfo)
844 {
845         if (xfs_hooks_switched_on(&xfs_rmap_hooks_switch)) {
846                 struct xfs_rmap_update_params   p = {
847                         .startblock     = startblock,
848                         .blockcount     = blockcount,
849                         .unwritten      = unwritten,
850                         .oinfo          = *oinfo, /* struct copy */
851                 };
852 
853                 if (pag)
854                         xfs_hooks_call(&pag->pag_rmap_update_hooks, op, &p);
855         }
856 }
857 
858 /* Call the specified function during a reverse mapping update. */
859 int
860 xfs_rmap_hook_add(
861         struct xfs_perag        *pag,
862         struct xfs_rmap_hook    *hook)
863 {
864         return xfs_hooks_add(&pag->pag_rmap_update_hooks, &hook->rmap_hook);
865 }
866 
867 /* Stop calling the specified function during a reverse mapping update. */
868 void
869 xfs_rmap_hook_del(
870         struct xfs_perag        *pag,
871         struct xfs_rmap_hook    *hook)
872 {
873         xfs_hooks_del(&pag->pag_rmap_update_hooks, &hook->rmap_hook);
874 }
875 
876 /* Configure rmap update hook functions. */
877 void
878 xfs_rmap_hook_setup(
879         struct xfs_rmap_hook    *hook,
880         notifier_fn_t           mod_fn)
881 {
882         xfs_hook_setup(&hook->rmap_hook, mod_fn);
883 }
884 #else
885 # define xfs_rmap_update_hook(t, p, o, s, b, u, oi)     do { } while (0)
886 #endif /* CONFIG_XFS_LIVE_HOOKS */
887 
888 /*
889  * Remove a reference to an extent in the rmap btree.
890  */
891 int
892 xfs_rmap_free(
893         struct xfs_trans                *tp,
894         struct xfs_buf                  *agbp,
895         struct xfs_perag                *pag,
896         xfs_agblock_t                   bno,
897         xfs_extlen_t                    len,
898         const struct xfs_owner_info     *oinfo)
899 {
900         struct xfs_mount                *mp = tp->t_mountp;
901         struct xfs_btree_cur            *cur;
902         int                             error;
903 
904         if (!xfs_has_rmapbt(mp))
905                 return 0;
906 
907         cur = xfs_rmapbt_init_cursor(mp, tp, agbp, pag);
908         xfs_rmap_update_hook(tp, pag, XFS_RMAP_UNMAP, bno, len, false, oinfo);
909         error = xfs_rmap_unmap(cur, bno, len, false, oinfo);
910 
911         xfs_btree_del_cursor(cur, error);
912         return error;
913 }
914 
915 /*
916  * A mergeable rmap must have the same owner and the same values for
917  * the unwritten, attr_fork, and bmbt flags.  The startblock and
918  * offset are checked separately.
919  */
920 static bool
921 xfs_rmap_is_mergeable(
922         struct xfs_rmap_irec    *irec,
923         uint64_t                owner,
924         unsigned int            flags)
925 {
926         if (irec->rm_owner == XFS_RMAP_OWN_NULL)
927                 return false;
928         if (irec->rm_owner != owner)
929                 return false;
930         if ((flags & XFS_RMAP_UNWRITTEN) ^
931             (irec->rm_flags & XFS_RMAP_UNWRITTEN))
932                 return false;
933         if ((flags & XFS_RMAP_ATTR_FORK) ^
934             (irec->rm_flags & XFS_RMAP_ATTR_FORK))
935                 return false;
936         if ((flags & XFS_RMAP_BMBT_BLOCK) ^
937             (irec->rm_flags & XFS_RMAP_BMBT_BLOCK))
938                 return false;
939         return true;
940 }
941 
942 /*
943  * When we allocate a new block, the first thing we do is add a reference to
944  * the extent in the rmap btree. This takes the form of a [agbno, length,
945  * owner, offset] record.  Flags are encoded in the high bits of the offset
946  * field.
947  */
948 STATIC int
949 xfs_rmap_map(
950         struct xfs_btree_cur            *cur,
951         xfs_agblock_t                   bno,
952         xfs_extlen_t                    len,
953         bool                            unwritten,
954         const struct xfs_owner_info     *oinfo)
955 {
956         struct xfs_mount                *mp = cur->bc_mp;
957         struct xfs_rmap_irec            ltrec;
958         struct xfs_rmap_irec            gtrec;
959         int                             have_gt;
960         int                             have_lt;
961         int                             error = 0;
962         int                             i;
963         uint64_t                        owner;
964         uint64_t                        offset;
965         unsigned int                    flags = 0;
966         bool                            ignore_off;
967 
968         xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
969         ASSERT(owner != 0);
970         ignore_off = XFS_RMAP_NON_INODE_OWNER(owner) ||
971                         (flags & XFS_RMAP_BMBT_BLOCK);
972         if (unwritten)
973                 flags |= XFS_RMAP_UNWRITTEN;
974         trace_xfs_rmap_map(cur, bno, len, unwritten, oinfo);
975         ASSERT(!xfs_rmap_should_skip_owner_update(oinfo));
976 
977         /*
978          * For the initial lookup, look for an exact match or the left-adjacent
979          * record for our insertion point. This will also give us the record for
980          * start block contiguity tests.
981          */
982         error = xfs_rmap_lookup_le(cur, bno, owner, offset, flags, &ltrec,
983                         &have_lt);
984         if (error)
985                 goto out_error;
986         if (have_lt) {
987                 trace_xfs_rmap_lookup_le_range_result(cur, ltrec.rm_startblock,
988                                 ltrec.rm_blockcount, ltrec.rm_owner,
989                                 ltrec.rm_offset, ltrec.rm_flags);
990 
991                 if (!xfs_rmap_is_mergeable(&ltrec, owner, flags))
992                         have_lt = 0;
993         }
994 
995         if (XFS_IS_CORRUPT(mp,
996                            have_lt != 0 &&
997                            ltrec.rm_startblock + ltrec.rm_blockcount > bno)) {
998                 xfs_btree_mark_sick(cur);
999                 error = -EFSCORRUPTED;
1000                 goto out_error;
1001         }
1002 
1003         /*
1004          * Increment the cursor to see if we have a right-adjacent record to our
1005          * insertion point. This will give us the record for end block
1006          * contiguity tests.
1007          */
1008         error = xfs_btree_increment(cur, 0, &have_gt);
1009         if (error)
1010                 goto out_error;
1011         if (have_gt) {
1012                 error = xfs_rmap_get_rec(cur, &gtrec, &have_gt);
1013                 if (error)
1014                         goto out_error;
1015                 if (XFS_IS_CORRUPT(mp, have_gt != 1)) {
1016                         xfs_btree_mark_sick(cur);
1017                         error = -EFSCORRUPTED;
1018                         goto out_error;
1019                 }
1020                 if (XFS_IS_CORRUPT(mp, bno + len > gtrec.rm_startblock)) {
1021                         xfs_btree_mark_sick(cur);
1022                         error = -EFSCORRUPTED;
1023                         goto out_error;
1024                 }
1025                 trace_xfs_rmap_find_right_neighbor_result(cur,
1026                                 gtrec.rm_startblock, gtrec.rm_blockcount,
1027                                 gtrec.rm_owner, gtrec.rm_offset,
1028                                 gtrec.rm_flags);
1029                 if (!xfs_rmap_is_mergeable(&gtrec, owner, flags))
1030                         have_gt = 0;
1031         }
1032 
1033         /*
1034          * Note: cursor currently points one record to the right of ltrec, even
1035          * if there is no record in the tree to the right.
1036          */
1037         if (have_lt &&
1038             ltrec.rm_startblock + ltrec.rm_blockcount == bno &&
1039             (ignore_off || ltrec.rm_offset + ltrec.rm_blockcount == offset)) {
1040                 /*
1041                  * left edge contiguous, merge into left record.
1042                  *
1043                  *       ltbno     ltlen
1044                  * orig:   |ooooooooo|
1045                  * adding:           |aaaaaaaaa|
1046                  * result: |rrrrrrrrrrrrrrrrrrr|
1047                  *                  bno       len
1048                  */
1049                 ltrec.rm_blockcount += len;
1050                 if (have_gt &&
1051                     bno + len == gtrec.rm_startblock &&
1052                     (ignore_off || offset + len == gtrec.rm_offset) &&
1053                     (unsigned long)ltrec.rm_blockcount + len +
1054                                 gtrec.rm_blockcount <= XFS_RMAP_LEN_MAX) {
1055                         /*
1056                          * right edge also contiguous, delete right record
1057                          * and merge into left record.
1058                          *
1059                          *       ltbno     ltlen    gtbno     gtlen
1060                          * orig:   |ooooooooo|         |ooooooooo|
1061                          * adding:           |aaaaaaaaa|
1062                          * result: |rrrrrrrrrrrrrrrrrrrrrrrrrrrrr|
1063                          */
1064                         ltrec.rm_blockcount += gtrec.rm_blockcount;
1065                         trace_xfs_rmap_delete(cur, gtrec.rm_startblock,
1066                                         gtrec.rm_blockcount, gtrec.rm_owner,
1067                                         gtrec.rm_offset, gtrec.rm_flags);
1068                         error = xfs_btree_delete(cur, &i);
1069                         if (error)
1070                                 goto out_error;
1071                         if (XFS_IS_CORRUPT(mp, i != 1)) {
1072                                 xfs_btree_mark_sick(cur);
1073                                 error = -EFSCORRUPTED;
1074                                 goto out_error;
1075                         }
1076                 }
1077 
1078                 /* point the cursor back to the left record and update */
1079                 error = xfs_btree_decrement(cur, 0, &have_gt);
1080                 if (error)
1081                         goto out_error;
1082                 error = xfs_rmap_update(cur, &ltrec);
1083                 if (error)
1084                         goto out_error;
1085         } else if (have_gt &&
1086                    bno + len == gtrec.rm_startblock &&
1087                    (ignore_off || offset + len == gtrec.rm_offset)) {
1088                 /*
1089                  * right edge contiguous, merge into right record.
1090                  *
1091                  *                 gtbno     gtlen
1092                  * Orig:             |ooooooooo|
1093                  * adding: |aaaaaaaaa|
1094                  * Result: |rrrrrrrrrrrrrrrrrrr|
1095                  *        bno       len
1096                  */
1097                 gtrec.rm_startblock = bno;
1098                 gtrec.rm_blockcount += len;
1099                 if (!ignore_off)
1100                         gtrec.rm_offset = offset;
1101                 error = xfs_rmap_update(cur, &gtrec);
1102                 if (error)
1103                         goto out_error;
1104         } else {
1105                 /*
1106                  * no contiguous edge with identical owner, insert
1107                  * new record at current cursor position.
1108                  */
1109                 cur->bc_rec.r.rm_startblock = bno;
1110                 cur->bc_rec.r.rm_blockcount = len;
1111                 cur->bc_rec.r.rm_owner = owner;
1112                 cur->bc_rec.r.rm_offset = offset;
1113                 cur->bc_rec.r.rm_flags = flags;
1114                 trace_xfs_rmap_insert(cur, bno, len, owner, offset, flags);
1115                 error = xfs_btree_insert(cur, &i);
1116                 if (error)
1117                         goto out_error;
1118                 if (XFS_IS_CORRUPT(mp, i != 1)) {
1119                         xfs_btree_mark_sick(cur);
1120                         error = -EFSCORRUPTED;
1121                         goto out_error;
1122                 }
1123         }
1124 
1125         trace_xfs_rmap_map_done(cur, bno, len, unwritten, oinfo);
1126 out_error:
1127         if (error)
1128                 trace_xfs_rmap_map_error(cur, error, _RET_IP_);
1129         return error;
1130 }
1131 
1132 /*
1133  * Add a reference to an extent in the rmap btree.
1134  */
1135 int
1136 xfs_rmap_alloc(
1137         struct xfs_trans                *tp,
1138         struct xfs_buf                  *agbp,
1139         struct xfs_perag                *pag,
1140         xfs_agblock_t                   bno,
1141         xfs_extlen_t                    len,
1142         const struct xfs_owner_info     *oinfo)
1143 {
1144         struct xfs_mount                *mp = tp->t_mountp;
1145         struct xfs_btree_cur            *cur;
1146         int                             error;
1147 
1148         if (!xfs_has_rmapbt(mp))
1149                 return 0;
1150 
1151         cur = xfs_rmapbt_init_cursor(mp, tp, agbp, pag);
1152         xfs_rmap_update_hook(tp, pag, XFS_RMAP_MAP, bno, len, false, oinfo);
1153         error = xfs_rmap_map(cur, bno, len, false, oinfo);
1154 
1155         xfs_btree_del_cursor(cur, error);
1156         return error;
1157 }
1158 
1159 #define RMAP_LEFT_CONTIG        (1 << 0)
1160 #define RMAP_RIGHT_CONTIG       (1 << 1)
1161 #define RMAP_LEFT_FILLING       (1 << 2)
1162 #define RMAP_RIGHT_FILLING      (1 << 3)
1163 #define RMAP_LEFT_VALID         (1 << 6)
1164 #define RMAP_RIGHT_VALID        (1 << 7)
1165 
1166 #define LEFT            r[0]
1167 #define RIGHT           r[1]
1168 #define PREV            r[2]
1169 #define NEW             r[3]
1170 
1171 /*
1172  * Convert an unwritten extent to a real extent or vice versa.
1173  * Does not handle overlapping extents.
1174  */
1175 STATIC int
1176 xfs_rmap_convert(
1177         struct xfs_btree_cur            *cur,
1178         xfs_agblock_t                   bno,
1179         xfs_extlen_t                    len,
1180         bool                            unwritten,
1181         const struct xfs_owner_info     *oinfo)
1182 {
1183         struct xfs_mount                *mp = cur->bc_mp;
1184         struct xfs_rmap_irec            r[4];   /* neighbor extent entries */
1185                                                 /* left is 0, right is 1, */
1186                                                 /* prev is 2, new is 3 */
1187         uint64_t                owner;
1188         uint64_t                offset;
1189         uint64_t                new_endoff;
1190         unsigned int            oldext;
1191         unsigned int            newext;
1192         unsigned int            flags = 0;
1193         int                     i;
1194         int                     state = 0;
1195         int                     error;
1196 
1197         xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
1198         ASSERT(!(XFS_RMAP_NON_INODE_OWNER(owner) ||
1199                         (flags & (XFS_RMAP_ATTR_FORK | XFS_RMAP_BMBT_BLOCK))));
1200         oldext = unwritten ? XFS_RMAP_UNWRITTEN : 0;
1201         new_endoff = offset + len;
1202         trace_xfs_rmap_convert(cur, bno, len, unwritten, oinfo);
1203 
1204         /*
1205          * For the initial lookup, look for an exact match or the left-adjacent
1206          * record for our insertion point. This will also give us the record for
1207          * start block contiguity tests.
1208          */
1209         error = xfs_rmap_lookup_le(cur, bno, owner, offset, oldext, &PREV, &i);
1210         if (error)
1211                 goto done;
1212         if (XFS_IS_CORRUPT(mp, i != 1)) {
1213                 xfs_btree_mark_sick(cur);
1214                 error = -EFSCORRUPTED;
1215                 goto done;
1216         }
1217 
1218         trace_xfs_rmap_lookup_le_range_result(cur, PREV.rm_startblock,
1219                         PREV.rm_blockcount, PREV.rm_owner, PREV.rm_offset,
1220                         PREV.rm_flags);
1221 
1222         ASSERT(PREV.rm_offset <= offset);
1223         ASSERT(PREV.rm_offset + PREV.rm_blockcount >= new_endoff);
1224         ASSERT((PREV.rm_flags & XFS_RMAP_UNWRITTEN) == oldext);
1225         newext = ~oldext & XFS_RMAP_UNWRITTEN;
1226 
1227         /*
1228          * Set flags determining what part of the previous oldext allocation
1229          * extent is being replaced by a newext allocation.
1230          */
1231         if (PREV.rm_offset == offset)
1232                 state |= RMAP_LEFT_FILLING;
1233         if (PREV.rm_offset + PREV.rm_blockcount == new_endoff)
1234                 state |= RMAP_RIGHT_FILLING;
1235 
1236         /*
1237          * Decrement the cursor to see if we have a left-adjacent record to our
1238          * insertion point. This will give us the record for end block
1239          * contiguity tests.
1240          */
1241         error = xfs_btree_decrement(cur, 0, &i);
1242         if (error)
1243                 goto done;
1244         if (i) {
1245                 state |= RMAP_LEFT_VALID;
1246                 error = xfs_rmap_get_rec(cur, &LEFT, &i);
1247                 if (error)
1248                         goto done;
1249                 if (XFS_IS_CORRUPT(mp, i != 1)) {
1250                         xfs_btree_mark_sick(cur);
1251                         error = -EFSCORRUPTED;
1252                         goto done;
1253                 }
1254                 if (XFS_IS_CORRUPT(mp,
1255                                    LEFT.rm_startblock + LEFT.rm_blockcount >
1256                                    bno)) {
1257                         xfs_btree_mark_sick(cur);
1258                         error = -EFSCORRUPTED;
1259                         goto done;
1260                 }
1261                 trace_xfs_rmap_find_left_neighbor_result(cur,
1262                                 LEFT.rm_startblock, LEFT.rm_blockcount,
1263                                 LEFT.rm_owner, LEFT.rm_offset, LEFT.rm_flags);
1264                 if (LEFT.rm_startblock + LEFT.rm_blockcount == bno &&
1265                     LEFT.rm_offset + LEFT.rm_blockcount == offset &&
1266                     xfs_rmap_is_mergeable(&LEFT, owner, newext))
1267                         state |= RMAP_LEFT_CONTIG;
1268         }
1269 
1270         /*
1271          * Increment the cursor to see if we have a right-adjacent record to our
1272          * insertion point. This will give us the record for end block
1273          * contiguity tests.
1274          */
1275         error = xfs_btree_increment(cur, 0, &i);
1276         if (error)
1277                 goto done;
1278         if (XFS_IS_CORRUPT(mp, i != 1)) {
1279                 xfs_btree_mark_sick(cur);
1280                 error = -EFSCORRUPTED;
1281                 goto done;
1282         }
1283         error = xfs_btree_increment(cur, 0, &i);
1284         if (error)
1285                 goto done;
1286         if (i) {
1287                 state |= RMAP_RIGHT_VALID;
1288                 error = xfs_rmap_get_rec(cur, &RIGHT, &i);
1289                 if (error)
1290                         goto done;
1291                 if (XFS_IS_CORRUPT(mp, i != 1)) {
1292                         xfs_btree_mark_sick(cur);
1293                         error = -EFSCORRUPTED;
1294                         goto done;
1295                 }
1296                 if (XFS_IS_CORRUPT(mp, bno + len > RIGHT.rm_startblock)) {
1297                         xfs_btree_mark_sick(cur);
1298                         error = -EFSCORRUPTED;
1299                         goto done;
1300                 }
1301                 trace_xfs_rmap_find_right_neighbor_result(cur,
1302                                 RIGHT.rm_startblock, RIGHT.rm_blockcount,
1303                                 RIGHT.rm_owner, RIGHT.rm_offset,
1304                                 RIGHT.rm_flags);
1305                 if (bno + len == RIGHT.rm_startblock &&
1306                     offset + len == RIGHT.rm_offset &&
1307                     xfs_rmap_is_mergeable(&RIGHT, owner, newext))
1308                         state |= RMAP_RIGHT_CONTIG;
1309         }
1310 
1311         /* check that left + prev + right is not too long */
1312         if ((state & (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1313                          RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG)) ==
1314             (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1315              RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG) &&
1316             (unsigned long)LEFT.rm_blockcount + len +
1317              RIGHT.rm_blockcount > XFS_RMAP_LEN_MAX)
1318                 state &= ~RMAP_RIGHT_CONTIG;
1319 
1320         trace_xfs_rmap_convert_state(cur, state, _RET_IP_);
1321 
1322         /* reset the cursor back to PREV */
1323         error = xfs_rmap_lookup_le(cur, bno, owner, offset, oldext, NULL, &i);
1324         if (error)
1325                 goto done;
1326         if (XFS_IS_CORRUPT(mp, i != 1)) {
1327                 xfs_btree_mark_sick(cur);
1328                 error = -EFSCORRUPTED;
1329                 goto done;
1330         }
1331 
1332         /*
1333          * Switch out based on the FILLING and CONTIG state bits.
1334          */
1335         switch (state & (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1336                          RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG)) {
1337         case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1338              RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG:
1339                 /*
1340                  * Setting all of a previous oldext extent to newext.
1341                  * The left and right neighbors are both contiguous with new.
1342                  */
1343                 error = xfs_btree_increment(cur, 0, &i);
1344                 if (error)
1345                         goto done;
1346                 if (XFS_IS_CORRUPT(mp, i != 1)) {
1347                         xfs_btree_mark_sick(cur);
1348                         error = -EFSCORRUPTED;
1349                         goto done;
1350                 }
1351                 trace_xfs_rmap_delete(cur, RIGHT.rm_startblock,
1352                                 RIGHT.rm_blockcount, RIGHT.rm_owner,
1353                                 RIGHT.rm_offset, RIGHT.rm_flags);
1354                 error = xfs_btree_delete(cur, &i);
1355                 if (error)
1356                         goto done;
1357                 if (XFS_IS_CORRUPT(mp, i != 1)) {
1358                         xfs_btree_mark_sick(cur);
1359                         error = -EFSCORRUPTED;
1360                         goto done;
1361                 }
1362                 error = xfs_btree_decrement(cur, 0, &i);
1363                 if (error)
1364                         goto done;
1365                 if (XFS_IS_CORRUPT(mp, i != 1)) {
1366                         xfs_btree_mark_sick(cur);
1367                         error = -EFSCORRUPTED;
1368                         goto done;
1369                 }
1370                 trace_xfs_rmap_delete(cur, PREV.rm_startblock,
1371                                 PREV.rm_blockcount, PREV.rm_owner,
1372                                 PREV.rm_offset, PREV.rm_flags);
1373                 error = xfs_btree_delete(cur, &i);
1374                 if (error)
1375                         goto done;
1376                 if (XFS_IS_CORRUPT(mp, i != 1)) {
1377                         xfs_btree_mark_sick(cur);
1378                         error = -EFSCORRUPTED;
1379                         goto done;
1380                 }
1381                 error = xfs_btree_decrement(cur, 0, &i);
1382                 if (error)
1383                         goto done;
1384                 if (XFS_IS_CORRUPT(mp, i != 1)) {
1385                         xfs_btree_mark_sick(cur);
1386                         error = -EFSCORRUPTED;
1387                         goto done;
1388                 }
1389                 NEW = LEFT;
1390                 NEW.rm_blockcount += PREV.rm_blockcount + RIGHT.rm_blockcount;
1391                 error = xfs_rmap_update(cur, &NEW);
1392                 if (error)
1393                         goto done;
1394                 break;
1395 
1396         case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG:
1397                 /*
1398                  * Setting all of a previous oldext extent to newext.
1399                  * The left neighbor is contiguous, the right is not.
1400                  */
1401                 trace_xfs_rmap_delete(cur, PREV.rm_startblock,
1402                                 PREV.rm_blockcount, PREV.rm_owner,
1403                                 PREV.rm_offset, PREV.rm_flags);
1404                 error = xfs_btree_delete(cur, &i);
1405                 if (error)
1406                         goto done;
1407                 if (XFS_IS_CORRUPT(mp, i != 1)) {
1408                         xfs_btree_mark_sick(cur);
1409                         error = -EFSCORRUPTED;
1410                         goto done;
1411                 }
1412                 error = xfs_btree_decrement(cur, 0, &i);
1413                 if (error)
1414                         goto done;
1415                 if (XFS_IS_CORRUPT(mp, i != 1)) {
1416                         xfs_btree_mark_sick(cur);
1417                         error = -EFSCORRUPTED;
1418                         goto done;
1419                 }
1420                 NEW = LEFT;
1421                 NEW.rm_blockcount += PREV.rm_blockcount;
1422                 error = xfs_rmap_update(cur, &NEW);
1423                 if (error)
1424                         goto done;
1425                 break;
1426 
1427         case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG:
1428                 /*
1429                  * Setting all of a previous oldext extent to newext.
1430                  * The right neighbor is contiguous, the left is not.
1431                  */
1432                 error = xfs_btree_increment(cur, 0, &i);
1433                 if (error)
1434                         goto done;
1435                 if (XFS_IS_CORRUPT(mp, i != 1)) {
1436                         xfs_btree_mark_sick(cur);
1437                         error = -EFSCORRUPTED;
1438                         goto done;
1439                 }
1440                 trace_xfs_rmap_delete(cur, RIGHT.rm_startblock,
1441                                 RIGHT.rm_blockcount, RIGHT.rm_owner,
1442                                 RIGHT.rm_offset, RIGHT.rm_flags);
1443                 error = xfs_btree_delete(cur, &i);
1444                 if (error)
1445                         goto done;
1446                 if (XFS_IS_CORRUPT(mp, i != 1)) {
1447                         xfs_btree_mark_sick(cur);
1448                         error = -EFSCORRUPTED;
1449                         goto done;
1450                 }
1451                 error = xfs_btree_decrement(cur, 0, &i);
1452                 if (error)
1453                         goto done;
1454                 if (XFS_IS_CORRUPT(mp, i != 1)) {
1455                         xfs_btree_mark_sick(cur);
1456                         error = -EFSCORRUPTED;
1457                         goto done;
1458                 }
1459                 NEW = PREV;
1460                 NEW.rm_blockcount = len + RIGHT.rm_blockcount;
1461                 NEW.rm_flags = newext;
1462                 error = xfs_rmap_update(cur, &NEW);
1463                 if (error)
1464                         goto done;
1465                 break;
1466 
1467         case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING:
1468                 /*
1469                  * Setting all of a previous oldext extent to newext.
1470                  * Neither the left nor right neighbors are contiguous with
1471                  * the new one.
1472                  */
1473                 NEW = PREV;
1474                 NEW.rm_flags = newext;
1475                 error = xfs_rmap_update(cur, &NEW);
1476                 if (error)
1477                         goto done;
1478                 break;
1479 
1480         case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG:
1481                 /*
1482                  * Setting the first part of a previous oldext extent to newext.
1483                  * The left neighbor is contiguous.
1484                  */
1485                 NEW = PREV;
1486                 NEW.rm_offset += len;
1487                 NEW.rm_startblock += len;
1488                 NEW.rm_blockcount -= len;
1489                 error = xfs_rmap_update(cur, &NEW);
1490                 if (error)
1491                         goto done;
1492                 error = xfs_btree_decrement(cur, 0, &i);
1493                 if (error)
1494                         goto done;
1495                 NEW = LEFT;
1496                 NEW.rm_blockcount += len;
1497                 error = xfs_rmap_update(cur, &NEW);
1498                 if (error)
1499                         goto done;
1500                 break;
1501 
1502         case RMAP_LEFT_FILLING:
1503                 /*
1504                  * Setting the first part of a previous oldext extent to newext.
1505                  * The left neighbor is not contiguous.
1506                  */
1507                 NEW = PREV;
1508                 NEW.rm_startblock += len;
1509                 NEW.rm_offset += len;
1510                 NEW.rm_blockcount -= len;
1511                 error = xfs_rmap_update(cur, &NEW);
1512                 if (error)
1513                         goto done;
1514                 NEW.rm_startblock = bno;
1515                 NEW.rm_owner = owner;
1516                 NEW.rm_offset = offset;
1517                 NEW.rm_blockcount = len;
1518                 NEW.rm_flags = newext;
1519                 cur->bc_rec.r = NEW;
1520                 trace_xfs_rmap_insert(cur, bno, len, owner, offset, newext);
1521                 error = xfs_btree_insert(cur, &i);
1522                 if (error)
1523                         goto done;
1524                 if (XFS_IS_CORRUPT(mp, i != 1)) {
1525                         xfs_btree_mark_sick(cur);
1526                         error = -EFSCORRUPTED;
1527                         goto done;
1528                 }
1529                 break;
1530 
1531         case RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG:
1532                 /*
1533                  * Setting the last part of a previous oldext extent to newext.
1534                  * The right neighbor is contiguous with the new allocation.
1535                  */
1536                 NEW = PREV;
1537                 NEW.rm_blockcount -= len;
1538                 error = xfs_rmap_update(cur, &NEW);
1539                 if (error)
1540                         goto done;
1541                 error = xfs_btree_increment(cur, 0, &i);
1542                 if (error)
1543                         goto done;
1544                 NEW = RIGHT;
1545                 NEW.rm_offset = offset;
1546                 NEW.rm_startblock = bno;
1547                 NEW.rm_blockcount += len;
1548                 error = xfs_rmap_update(cur, &NEW);
1549                 if (error)
1550                         goto done;
1551                 break;
1552 
1553         case RMAP_RIGHT_FILLING:
1554                 /*
1555                  * Setting the last part of a previous oldext extent to newext.
1556                  * The right neighbor is not contiguous.
1557                  */
1558                 NEW = PREV;
1559                 NEW.rm_blockcount -= len;
1560                 error = xfs_rmap_update(cur, &NEW);
1561                 if (error)
1562                         goto done;
1563                 error = xfs_rmap_lookup_eq(cur, bno, len, owner, offset,
1564                                 oldext, &i);
1565                 if (error)
1566                         goto done;
1567                 if (XFS_IS_CORRUPT(mp, i != 0)) {
1568                         xfs_btree_mark_sick(cur);
1569                         error = -EFSCORRUPTED;
1570                         goto done;
1571                 }
1572                 NEW.rm_startblock = bno;
1573                 NEW.rm_owner = owner;
1574                 NEW.rm_offset = offset;
1575                 NEW.rm_blockcount = len;
1576                 NEW.rm_flags = newext;
1577                 cur->bc_rec.r = NEW;
1578                 trace_xfs_rmap_insert(cur, bno, len, owner, offset, newext);
1579                 error = xfs_btree_insert(cur, &i);
1580                 if (error)
1581                         goto done;
1582                 if (XFS_IS_CORRUPT(mp, i != 1)) {
1583                         xfs_btree_mark_sick(cur);
1584                         error = -EFSCORRUPTED;
1585                         goto done;
1586                 }
1587                 break;
1588 
1589         case 0:
1590                 /*
1591                  * Setting the middle part of a previous oldext extent to
1592                  * newext.  Contiguity is impossible here.
1593                  * One extent becomes three extents.
1594                  */
1595                 /* new right extent - oldext */
1596                 NEW.rm_startblock = bno + len;
1597                 NEW.rm_owner = owner;
1598                 NEW.rm_offset = new_endoff;
1599                 NEW.rm_blockcount = PREV.rm_offset + PREV.rm_blockcount -
1600                                 new_endoff;
1601                 NEW.rm_flags = PREV.rm_flags;
1602                 error = xfs_rmap_update(cur, &NEW);
1603                 if (error)
1604                         goto done;
1605                 /* new left extent - oldext */
1606                 NEW = PREV;
1607                 NEW.rm_blockcount = offset - PREV.rm_offset;
1608                 cur->bc_rec.r = NEW;
1609                 trace_xfs_rmap_insert(cur, NEW.rm_startblock,
1610                                 NEW.rm_blockcount, NEW.rm_owner, NEW.rm_offset,
1611                                 NEW.rm_flags);
1612                 error = xfs_btree_insert(cur, &i);
1613                 if (error)
1614                         goto done;
1615                 if (XFS_IS_CORRUPT(mp, i != 1)) {
1616                         xfs_btree_mark_sick(cur);
1617                         error = -EFSCORRUPTED;
1618                         goto done;
1619                 }
1620                 /*
1621                  * Reset the cursor to the position of the new extent
1622                  * we are about to insert as we can't trust it after
1623                  * the previous insert.
1624                  */
1625                 error = xfs_rmap_lookup_eq(cur, bno, len, owner, offset,
1626                                 oldext, &i);
1627                 if (error)
1628                         goto done;
1629                 if (XFS_IS_CORRUPT(mp, i != 0)) {
1630                         xfs_btree_mark_sick(cur);
1631                         error = -EFSCORRUPTED;
1632                         goto done;
1633                 }
1634                 /* new middle extent - newext */
1635                 cur->bc_rec.r.rm_flags &= ~XFS_RMAP_UNWRITTEN;
1636                 cur->bc_rec.r.rm_flags |= newext;
1637                 trace_xfs_rmap_insert(cur, bno, len, owner, offset, newext);
1638                 error = xfs_btree_insert(cur, &i);
1639                 if (error)
1640                         goto done;
1641                 if (XFS_IS_CORRUPT(mp, i != 1)) {
1642                         xfs_btree_mark_sick(cur);
1643                         error = -EFSCORRUPTED;
1644                         goto done;
1645                 }
1646                 break;
1647 
1648         case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG:
1649         case RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG:
1650         case RMAP_LEFT_FILLING | RMAP_RIGHT_CONTIG:
1651         case RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG:
1652         case RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG:
1653         case RMAP_LEFT_CONTIG:
1654         case RMAP_RIGHT_CONTIG:
1655                 /*
1656                  * These cases are all impossible.
1657                  */
1658                 ASSERT(0);
1659         }
1660 
1661         trace_xfs_rmap_convert_done(cur, bno, len, unwritten, oinfo);
1662 done:
1663         if (error)
1664                 trace_xfs_rmap_convert_error(cur, error, _RET_IP_);
1665         return error;
1666 }
1667 
1668 /*
1669  * Convert an unwritten extent to a real extent or vice versa.  If there is no
1670  * possibility of overlapping extents, delegate to the simpler convert
1671  * function.
1672  */
1673 STATIC int
1674 xfs_rmap_convert_shared(
1675         struct xfs_btree_cur            *cur,
1676         xfs_agblock_t                   bno,
1677         xfs_extlen_t                    len,
1678         bool                            unwritten,
1679         const struct xfs_owner_info     *oinfo)
1680 {
1681         struct xfs_mount                *mp = cur->bc_mp;
1682         struct xfs_rmap_irec            r[4];   /* neighbor extent entries */
1683                                                 /* left is 0, right is 1, */
1684                                                 /* prev is 2, new is 3 */
1685         uint64_t                owner;
1686         uint64_t                offset;
1687         uint64_t                new_endoff;
1688         unsigned int            oldext;
1689         unsigned int            newext;
1690         unsigned int            flags = 0;
1691         int                     i;
1692         int                     state = 0;
1693         int                     error;
1694 
1695         xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
1696         ASSERT(!(XFS_RMAP_NON_INODE_OWNER(owner) ||
1697                         (flags & (XFS_RMAP_ATTR_FORK | XFS_RMAP_BMBT_BLOCK))));
1698         oldext = unwritten ? XFS_RMAP_UNWRITTEN : 0;
1699         new_endoff = offset + len;
1700         trace_xfs_rmap_convert(cur, bno, len, unwritten, oinfo);
1701 
1702         /*
1703          * For the initial lookup, look for and exact match or the left-adjacent
1704          * record for our insertion point. This will also give us the record for
1705          * start block contiguity tests.
1706          */
1707         error = xfs_rmap_lookup_le_range(cur, bno, owner, offset, oldext,
1708                         &PREV, &i);
1709         if (error)
1710                 goto done;
1711         if (XFS_IS_CORRUPT(mp, i != 1)) {
1712                 xfs_btree_mark_sick(cur);
1713                 error = -EFSCORRUPTED;
1714                 goto done;
1715         }
1716 
1717         ASSERT(PREV.rm_offset <= offset);
1718         ASSERT(PREV.rm_offset + PREV.rm_blockcount >= new_endoff);
1719         ASSERT((PREV.rm_flags & XFS_RMAP_UNWRITTEN) == oldext);
1720         newext = ~oldext & XFS_RMAP_UNWRITTEN;
1721 
1722         /*
1723          * Set flags determining what part of the previous oldext allocation
1724          * extent is being replaced by a newext allocation.
1725          */
1726         if (PREV.rm_offset == offset)
1727                 state |= RMAP_LEFT_FILLING;
1728         if (PREV.rm_offset + PREV.rm_blockcount == new_endoff)
1729                 state |= RMAP_RIGHT_FILLING;
1730 
1731         /* Is there a left record that abuts our range? */
1732         error = xfs_rmap_find_left_neighbor(cur, bno, owner, offset, newext,
1733                         &LEFT, &i);
1734         if (error)
1735                 goto done;
1736         if (i) {
1737                 state |= RMAP_LEFT_VALID;
1738                 if (XFS_IS_CORRUPT(mp,
1739                                    LEFT.rm_startblock + LEFT.rm_blockcount >
1740                                    bno)) {
1741                         xfs_btree_mark_sick(cur);
1742                         error = -EFSCORRUPTED;
1743                         goto done;
1744                 }
1745                 if (xfs_rmap_is_mergeable(&LEFT, owner, newext))
1746                         state |= RMAP_LEFT_CONTIG;
1747         }
1748 
1749         /* Is there a right record that abuts our range? */
1750         error = xfs_rmap_lookup_eq(cur, bno + len, len, owner, offset + len,
1751                         newext, &i);
1752         if (error)
1753                 goto done;
1754         if (i) {
1755                 state |= RMAP_RIGHT_VALID;
1756                 error = xfs_rmap_get_rec(cur, &RIGHT, &i);
1757                 if (error)
1758                         goto done;
1759                 if (XFS_IS_CORRUPT(mp, i != 1)) {
1760                         xfs_btree_mark_sick(cur);
1761                         error = -EFSCORRUPTED;
1762                         goto done;
1763                 }
1764                 if (XFS_IS_CORRUPT(mp, bno + len > RIGHT.rm_startblock)) {
1765                         xfs_btree_mark_sick(cur);
1766                         error = -EFSCORRUPTED;
1767                         goto done;
1768                 }
1769                 trace_xfs_rmap_find_right_neighbor_result(cur,
1770                                 RIGHT.rm_startblock, RIGHT.rm_blockcount,
1771                                 RIGHT.rm_owner, RIGHT.rm_offset,
1772                                 RIGHT.rm_flags);
1773                 if (xfs_rmap_is_mergeable(&RIGHT, owner, newext))
1774                         state |= RMAP_RIGHT_CONTIG;
1775         }
1776 
1777         /* check that left + prev + right is not too long */
1778         if ((state & (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1779                          RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG)) ==
1780             (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1781              RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG) &&
1782             (unsigned long)LEFT.rm_blockcount + len +
1783              RIGHT.rm_blockcount > XFS_RMAP_LEN_MAX)
1784                 state &= ~RMAP_RIGHT_CONTIG;
1785 
1786         trace_xfs_rmap_convert_state(cur, state, _RET_IP_);
1787         /*
1788          * Switch out based on the FILLING and CONTIG state bits.
1789          */
1790         switch (state & (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1791                          RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG)) {
1792         case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG |
1793              RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG:
1794                 /*
1795                  * Setting all of a previous oldext extent to newext.
1796                  * The left and right neighbors are both contiguous with new.
1797                  */
1798                 error = xfs_rmap_delete(cur, RIGHT.rm_startblock,
1799                                 RIGHT.rm_blockcount, RIGHT.rm_owner,
1800                                 RIGHT.rm_offset, RIGHT.rm_flags);
1801                 if (error)
1802                         goto done;
1803                 error = xfs_rmap_delete(cur, PREV.rm_startblock,
1804                                 PREV.rm_blockcount, PREV.rm_owner,
1805                                 PREV.rm_offset, PREV.rm_flags);
1806                 if (error)
1807                         goto done;
1808                 NEW = LEFT;
1809                 error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1810                                 NEW.rm_blockcount, NEW.rm_owner,
1811                                 NEW.rm_offset, NEW.rm_flags, &i);
1812                 if (error)
1813                         goto done;
1814                 if (XFS_IS_CORRUPT(mp, i != 1)) {
1815                         xfs_btree_mark_sick(cur);
1816                         error = -EFSCORRUPTED;
1817                         goto done;
1818                 }
1819                 NEW.rm_blockcount += PREV.rm_blockcount + RIGHT.rm_blockcount;
1820                 error = xfs_rmap_update(cur, &NEW);
1821                 if (error)
1822                         goto done;
1823                 break;
1824 
1825         case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG:
1826                 /*
1827                  * Setting all of a previous oldext extent to newext.
1828                  * The left neighbor is contiguous, the right is not.
1829                  */
1830                 error = xfs_rmap_delete(cur, PREV.rm_startblock,
1831                                 PREV.rm_blockcount, PREV.rm_owner,
1832                                 PREV.rm_offset, PREV.rm_flags);
1833                 if (error)
1834                         goto done;
1835                 NEW = LEFT;
1836                 error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1837                                 NEW.rm_blockcount, NEW.rm_owner,
1838                                 NEW.rm_offset, NEW.rm_flags, &i);
1839                 if (error)
1840                         goto done;
1841                 if (XFS_IS_CORRUPT(mp, i != 1)) {
1842                         xfs_btree_mark_sick(cur);
1843                         error = -EFSCORRUPTED;
1844                         goto done;
1845                 }
1846                 NEW.rm_blockcount += PREV.rm_blockcount;
1847                 error = xfs_rmap_update(cur, &NEW);
1848                 if (error)
1849                         goto done;
1850                 break;
1851 
1852         case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG:
1853                 /*
1854                  * Setting all of a previous oldext extent to newext.
1855                  * The right neighbor is contiguous, the left is not.
1856                  */
1857                 error = xfs_rmap_delete(cur, RIGHT.rm_startblock,
1858                                 RIGHT.rm_blockcount, RIGHT.rm_owner,
1859                                 RIGHT.rm_offset, RIGHT.rm_flags);
1860                 if (error)
1861                         goto done;
1862                 NEW = PREV;
1863                 error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1864                                 NEW.rm_blockcount, NEW.rm_owner,
1865                                 NEW.rm_offset, NEW.rm_flags, &i);
1866                 if (error)
1867                         goto done;
1868                 if (XFS_IS_CORRUPT(mp, i != 1)) {
1869                         xfs_btree_mark_sick(cur);
1870                         error = -EFSCORRUPTED;
1871                         goto done;
1872                 }
1873                 NEW.rm_blockcount += RIGHT.rm_blockcount;
1874                 NEW.rm_flags = RIGHT.rm_flags;
1875                 error = xfs_rmap_update(cur, &NEW);
1876                 if (error)
1877                         goto done;
1878                 break;
1879 
1880         case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING:
1881                 /*
1882                  * Setting all of a previous oldext extent to newext.
1883                  * Neither the left nor right neighbors are contiguous with
1884                  * the new one.
1885                  */
1886                 NEW = PREV;
1887                 error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1888                                 NEW.rm_blockcount, NEW.rm_owner,
1889                                 NEW.rm_offset, NEW.rm_flags, &i);
1890                 if (error)
1891                         goto done;
1892                 if (XFS_IS_CORRUPT(mp, i != 1)) {
1893                         xfs_btree_mark_sick(cur);
1894                         error = -EFSCORRUPTED;
1895                         goto done;
1896                 }
1897                 NEW.rm_flags = newext;
1898                 error = xfs_rmap_update(cur, &NEW);
1899                 if (error)
1900                         goto done;
1901                 break;
1902 
1903         case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG:
1904                 /*
1905                  * Setting the first part of a previous oldext extent to newext.
1906                  * The left neighbor is contiguous.
1907                  */
1908                 NEW = PREV;
1909                 error = xfs_rmap_delete(cur, NEW.rm_startblock,
1910                                 NEW.rm_blockcount, NEW.rm_owner,
1911                                 NEW.rm_offset, NEW.rm_flags);
1912                 if (error)
1913                         goto done;
1914                 NEW.rm_offset += len;
1915                 NEW.rm_startblock += len;
1916                 NEW.rm_blockcount -= len;
1917                 error = xfs_rmap_insert(cur, NEW.rm_startblock,
1918                                 NEW.rm_blockcount, NEW.rm_owner,
1919                                 NEW.rm_offset, NEW.rm_flags);
1920                 if (error)
1921                         goto done;
1922                 NEW = LEFT;
1923                 error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1924                                 NEW.rm_blockcount, NEW.rm_owner,
1925                                 NEW.rm_offset, NEW.rm_flags, &i);
1926                 if (error)
1927                         goto done;
1928                 if (XFS_IS_CORRUPT(mp, i != 1)) {
1929                         xfs_btree_mark_sick(cur);
1930                         error = -EFSCORRUPTED;
1931                         goto done;
1932                 }
1933                 NEW.rm_blockcount += len;
1934                 error = xfs_rmap_update(cur, &NEW);
1935                 if (error)
1936                         goto done;
1937                 break;
1938 
1939         case RMAP_LEFT_FILLING:
1940                 /*
1941                  * Setting the first part of a previous oldext extent to newext.
1942                  * The left neighbor is not contiguous.
1943                  */
1944                 NEW = PREV;
1945                 error = xfs_rmap_delete(cur, NEW.rm_startblock,
1946                                 NEW.rm_blockcount, NEW.rm_owner,
1947                                 NEW.rm_offset, NEW.rm_flags);
1948                 if (error)
1949                         goto done;
1950                 NEW.rm_offset += len;
1951                 NEW.rm_startblock += len;
1952                 NEW.rm_blockcount -= len;
1953                 error = xfs_rmap_insert(cur, NEW.rm_startblock,
1954                                 NEW.rm_blockcount, NEW.rm_owner,
1955                                 NEW.rm_offset, NEW.rm_flags);
1956                 if (error)
1957                         goto done;
1958                 error = xfs_rmap_insert(cur, bno, len, owner, offset, newext);
1959                 if (error)
1960                         goto done;
1961                 break;
1962 
1963         case RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG:
1964                 /*
1965                  * Setting the last part of a previous oldext extent to newext.
1966                  * The right neighbor is contiguous with the new allocation.
1967                  */
1968                 NEW = PREV;
1969                 error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
1970                                 NEW.rm_blockcount, NEW.rm_owner,
1971                                 NEW.rm_offset, NEW.rm_flags, &i);
1972                 if (error)
1973                         goto done;
1974                 if (XFS_IS_CORRUPT(mp, i != 1)) {
1975                         xfs_btree_mark_sick(cur);
1976                         error = -EFSCORRUPTED;
1977                         goto done;
1978                 }
1979                 NEW.rm_blockcount = offset - NEW.rm_offset;
1980                 error = xfs_rmap_update(cur, &NEW);
1981                 if (error)
1982                         goto done;
1983                 NEW = RIGHT;
1984                 error = xfs_rmap_delete(cur, NEW.rm_startblock,
1985                                 NEW.rm_blockcount, NEW.rm_owner,
1986                                 NEW.rm_offset, NEW.rm_flags);
1987                 if (error)
1988                         goto done;
1989                 NEW.rm_offset = offset;
1990                 NEW.rm_startblock = bno;
1991                 NEW.rm_blockcount += len;
1992                 error = xfs_rmap_insert(cur, NEW.rm_startblock,
1993                                 NEW.rm_blockcount, NEW.rm_owner,
1994                                 NEW.rm_offset, NEW.rm_flags);
1995                 if (error)
1996                         goto done;
1997                 break;
1998 
1999         case RMAP_RIGHT_FILLING:
2000                 /*
2001                  * Setting the last part of a previous oldext extent to newext.
2002                  * The right neighbor is not contiguous.
2003                  */
2004                 NEW = PREV;
2005                 error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
2006                                 NEW.rm_blockcount, NEW.rm_owner,
2007                                 NEW.rm_offset, NEW.rm_flags, &i);
2008                 if (error)
2009                         goto done;
2010                 if (XFS_IS_CORRUPT(mp, i != 1)) {
2011                         xfs_btree_mark_sick(cur);
2012                         error = -EFSCORRUPTED;
2013                         goto done;
2014                 }
2015                 NEW.rm_blockcount -= len;
2016                 error = xfs_rmap_update(cur, &NEW);
2017                 if (error)
2018                         goto done;
2019                 error = xfs_rmap_insert(cur, bno, len, owner, offset, newext);
2020                 if (error)
2021                         goto done;
2022                 break;
2023 
2024         case 0:
2025                 /*
2026                  * Setting the middle part of a previous oldext extent to
2027                  * newext.  Contiguity is impossible here.
2028                  * One extent becomes three extents.
2029                  */
2030                 /* new right extent - oldext */
2031                 NEW.rm_startblock = bno + len;
2032                 NEW.rm_owner = owner;
2033                 NEW.rm_offset = new_endoff;
2034                 NEW.rm_blockcount = PREV.rm_offset + PREV.rm_blockcount -
2035                                 new_endoff;
2036                 NEW.rm_flags = PREV.rm_flags;
2037                 error = xfs_rmap_insert(cur, NEW.rm_startblock,
2038                                 NEW.rm_blockcount, NEW.rm_owner, NEW.rm_offset,
2039                                 NEW.rm_flags);
2040                 if (error)
2041                         goto done;
2042                 /* new left extent - oldext */
2043                 NEW = PREV;
2044                 error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock,
2045                                 NEW.rm_blockcount, NEW.rm_owner,
2046                                 NEW.rm_offset, NEW.rm_flags, &i);
2047                 if (error)
2048                         goto done;
2049                 if (XFS_IS_CORRUPT(mp, i != 1)) {
2050                         xfs_btree_mark_sick(cur);
2051                         error = -EFSCORRUPTED;
2052                         goto done;
2053                 }
2054                 NEW.rm_blockcount = offset - NEW.rm_offset;
2055                 error = xfs_rmap_update(cur, &NEW);
2056                 if (error)
2057                         goto done;
2058                 /* new middle extent - newext */
2059                 NEW.rm_startblock = bno;
2060                 NEW.rm_blockcount = len;
2061                 NEW.rm_owner = owner;
2062                 NEW.rm_offset = offset;
2063                 NEW.rm_flags = newext;
2064                 error = xfs_rmap_insert(cur, NEW.rm_startblock,
2065                                 NEW.rm_blockcount, NEW.rm_owner, NEW.rm_offset,
2066                                 NEW.rm_flags);
2067                 if (error)
2068                         goto done;
2069                 break;
2070 
2071         case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG:
2072         case RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG:
2073         case RMAP_LEFT_FILLING | RMAP_RIGHT_CONTIG:
2074         case RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG:
2075         case RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG:
2076         case RMAP_LEFT_CONTIG:
2077         case RMAP_RIGHT_CONTIG:
2078                 /*
2079                  * These cases are all impossible.
2080                  */
2081                 ASSERT(0);
2082         }
2083 
2084         trace_xfs_rmap_convert_done(cur, bno, len, unwritten, oinfo);
2085 done:
2086         if (error)
2087                 trace_xfs_rmap_convert_error(cur, error, _RET_IP_);
2088         return error;
2089 }
2090 
2091 #undef  NEW
2092 #undef  LEFT
2093 #undef  RIGHT
2094 #undef  PREV
2095 
2096 /*
2097  * Find an extent in the rmap btree and unmap it.  For rmap extent types that
2098  * can overlap (data fork rmaps on reflink filesystems) we must be careful
2099  * that the prev/next records in the btree might belong to another owner.
2100  * Therefore we must use delete+insert to alter any of the key fields.
2101  *
2102  * For every other situation there can only be one owner for a given extent,
2103  * so we can call the regular _free function.
2104  */
2105 STATIC int
2106 xfs_rmap_unmap_shared(
2107         struct xfs_btree_cur            *cur,
2108         xfs_agblock_t                   bno,
2109         xfs_extlen_t                    len,
2110         bool                            unwritten,
2111         const struct xfs_owner_info     *oinfo)
2112 {
2113         struct xfs_mount                *mp = cur->bc_mp;
2114         struct xfs_rmap_irec            ltrec;
2115         uint64_t                        ltoff;
2116         int                             error = 0;
2117         int                             i;
2118         uint64_t                        owner;
2119         uint64_t                        offset;
2120         unsigned int                    flags;
2121 
2122         xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
2123         if (unwritten)
2124                 flags |= XFS_RMAP_UNWRITTEN;
2125         trace_xfs_rmap_unmap(cur, bno, len, unwritten, oinfo);
2126 
2127         /*
2128          * We should always have a left record because there's a static record
2129          * for the AG headers at rm_startblock == 0 created by mkfs/growfs that
2130          * will not ever be removed from the tree.
2131          */
2132         error = xfs_rmap_lookup_le_range(cur, bno, owner, offset, flags,
2133                         &ltrec, &i);
2134         if (error)
2135                 goto out_error;
2136         if (XFS_IS_CORRUPT(mp, i != 1)) {
2137                 xfs_btree_mark_sick(cur);
2138                 error = -EFSCORRUPTED;
2139                 goto out_error;
2140         }
2141         ltoff = ltrec.rm_offset;
2142 
2143         /* Make sure the extent we found covers the entire freeing range. */
2144         if (XFS_IS_CORRUPT(mp,
2145                            ltrec.rm_startblock > bno ||
2146                            ltrec.rm_startblock + ltrec.rm_blockcount <
2147                            bno + len)) {
2148                 xfs_btree_mark_sick(cur);
2149                 error = -EFSCORRUPTED;
2150                 goto out_error;
2151         }
2152 
2153         /* Make sure the owner matches what we expect to find in the tree. */
2154         if (XFS_IS_CORRUPT(mp, owner != ltrec.rm_owner)) {
2155                 xfs_btree_mark_sick(cur);
2156                 error = -EFSCORRUPTED;
2157                 goto out_error;
2158         }
2159 
2160         /* Make sure the unwritten flag matches. */
2161         if (XFS_IS_CORRUPT(mp,
2162                            (flags & XFS_RMAP_UNWRITTEN) !=
2163                            (ltrec.rm_flags & XFS_RMAP_UNWRITTEN))) {
2164                 xfs_btree_mark_sick(cur);
2165                 error = -EFSCORRUPTED;
2166                 goto out_error;
2167         }
2168 
2169         /* Check the offset. */
2170         if (XFS_IS_CORRUPT(mp, ltrec.rm_offset > offset)) {
2171                 xfs_btree_mark_sick(cur);
2172                 error = -EFSCORRUPTED;
2173                 goto out_error;
2174         }
2175         if (XFS_IS_CORRUPT(mp, offset > ltoff + ltrec.rm_blockcount)) {
2176                 xfs_btree_mark_sick(cur);
2177                 error = -EFSCORRUPTED;
2178                 goto out_error;
2179         }
2180 
2181         if (ltrec.rm_startblock == bno && ltrec.rm_blockcount == len) {
2182                 /* Exact match, simply remove the record from rmap tree. */
2183                 error = xfs_rmap_delete(cur, ltrec.rm_startblock,
2184                                 ltrec.rm_blockcount, ltrec.rm_owner,
2185                                 ltrec.rm_offset, ltrec.rm_flags);
2186                 if (error)
2187                         goto out_error;
2188         } else if (ltrec.rm_startblock == bno) {
2189                 /*
2190                  * Overlap left hand side of extent: move the start, trim the
2191                  * length and update the current record.
2192                  *
2193                  *       ltbno                ltlen
2194                  * Orig:    |oooooooooooooooooooo|
2195                  * Freeing: |fffffffff|
2196                  * Result:            |rrrrrrrrrr|
2197                  *         bno       len
2198                  */
2199 
2200                 /* Delete prev rmap. */
2201                 error = xfs_rmap_delete(cur, ltrec.rm_startblock,
2202                                 ltrec.rm_blockcount, ltrec.rm_owner,
2203                                 ltrec.rm_offset, ltrec.rm_flags);
2204                 if (error)
2205                         goto out_error;
2206 
2207                 /* Add an rmap at the new offset. */
2208                 ltrec.rm_startblock += len;
2209                 ltrec.rm_blockcount -= len;
2210                 ltrec.rm_offset += len;
2211                 error = xfs_rmap_insert(cur, ltrec.rm_startblock,
2212                                 ltrec.rm_blockcount, ltrec.rm_owner,
2213                                 ltrec.rm_offset, ltrec.rm_flags);
2214                 if (error)
2215                         goto out_error;
2216         } else if (ltrec.rm_startblock + ltrec.rm_blockcount == bno + len) {
2217                 /*
2218                  * Overlap right hand side of extent: trim the length and
2219                  * update the current record.
2220                  *
2221                  *       ltbno                ltlen
2222                  * Orig:    |oooooooooooooooooooo|
2223                  * Freeing:            |fffffffff|
2224                  * Result:  |rrrrrrrrrr|
2225                  *                    bno       len
2226                  */
2227                 error = xfs_rmap_lookup_eq(cur, ltrec.rm_startblock,
2228                                 ltrec.rm_blockcount, ltrec.rm_owner,
2229                                 ltrec.rm_offset, ltrec.rm_flags, &i);
2230                 if (error)
2231                         goto out_error;
2232                 if (XFS_IS_CORRUPT(mp, i != 1)) {
2233                         xfs_btree_mark_sick(cur);
2234                         error = -EFSCORRUPTED;
2235                         goto out_error;
2236                 }
2237                 ltrec.rm_blockcount -= len;
2238                 error = xfs_rmap_update(cur, &ltrec);
2239                 if (error)
2240                         goto out_error;
2241         } else {
2242                 /*
2243                  * Overlap middle of extent: trim the length of the existing
2244                  * record to the length of the new left-extent size, increment
2245                  * the insertion position so we can insert a new record
2246                  * containing the remaining right-extent space.
2247                  *
2248                  *       ltbno                ltlen
2249                  * Orig:    |oooooooooooooooooooo|
2250                  * Freeing:       |fffffffff|
2251                  * Result:  |rrrrr|         |rrrr|
2252                  *               bno       len
2253                  */
2254                 xfs_extlen_t    orig_len = ltrec.rm_blockcount;
2255 
2256                 /* Shrink the left side of the rmap */
2257                 error = xfs_rmap_lookup_eq(cur, ltrec.rm_startblock,
2258                                 ltrec.rm_blockcount, ltrec.rm_owner,
2259                                 ltrec.rm_offset, ltrec.rm_flags, &i);
2260                 if (error)
2261                         goto out_error;
2262                 if (XFS_IS_CORRUPT(mp, i != 1)) {
2263                         xfs_btree_mark_sick(cur);
2264                         error = -EFSCORRUPTED;
2265                         goto out_error;
2266                 }
2267                 ltrec.rm_blockcount = bno - ltrec.rm_startblock;
2268                 error = xfs_rmap_update(cur, &ltrec);
2269                 if (error)
2270                         goto out_error;
2271 
2272                 /* Add an rmap at the new offset */
2273                 error = xfs_rmap_insert(cur, bno + len,
2274                                 orig_len - len - ltrec.rm_blockcount,
2275                                 ltrec.rm_owner, offset + len,
2276                                 ltrec.rm_flags);
2277                 if (error)
2278                         goto out_error;
2279         }
2280 
2281         trace_xfs_rmap_unmap_done(cur, bno, len, unwritten, oinfo);
2282 out_error:
2283         if (error)
2284                 trace_xfs_rmap_unmap_error(cur, error, _RET_IP_);
2285         return error;
2286 }
2287 
2288 /*
2289  * Find an extent in the rmap btree and map it.  For rmap extent types that
2290  * can overlap (data fork rmaps on reflink filesystems) we must be careful
2291  * that the prev/next records in the btree might belong to another owner.
2292  * Therefore we must use delete+insert to alter any of the key fields.
2293  *
2294  * For every other situation there can only be one owner for a given extent,
2295  * so we can call the regular _alloc function.
2296  */
2297 STATIC int
2298 xfs_rmap_map_shared(
2299         struct xfs_btree_cur            *cur,
2300         xfs_agblock_t                   bno,
2301         xfs_extlen_t                    len,
2302         bool                            unwritten,
2303         const struct xfs_owner_info     *oinfo)
2304 {
2305         struct xfs_mount                *mp = cur->bc_mp;
2306         struct xfs_rmap_irec            ltrec;
2307         struct xfs_rmap_irec            gtrec;
2308         int                             have_gt;
2309         int                             have_lt;
2310         int                             error = 0;
2311         int                             i;
2312         uint64_t                        owner;
2313         uint64_t                        offset;
2314         unsigned int                    flags = 0;
2315 
2316         xfs_owner_info_unpack(oinfo, &owner, &offset, &flags);
2317         if (unwritten)
2318                 flags |= XFS_RMAP_UNWRITTEN;
2319         trace_xfs_rmap_map(cur, bno, len, unwritten, oinfo);
2320 
2321         /* Is there a left record that abuts our range? */
2322         error = xfs_rmap_find_left_neighbor(cur, bno, owner, offset, flags,
2323                         &ltrec, &have_lt);
2324         if (error)
2325                 goto out_error;
2326         if (have_lt &&
2327             !xfs_rmap_is_mergeable(&ltrec, owner, flags))
2328                 have_lt = 0;
2329 
2330         /* Is there a right record that abuts our range? */
2331         error = xfs_rmap_lookup_eq(cur, bno + len, len, owner, offset + len,
2332                         flags, &have_gt);
2333         if (error)
2334                 goto out_error;
2335         if (have_gt) {
2336                 error = xfs_rmap_get_rec(cur, &gtrec, &have_gt);
2337                 if (error)
2338                         goto out_error;
2339                 if (XFS_IS_CORRUPT(mp, have_gt != 1)) {
2340                         xfs_btree_mark_sick(cur);
2341                         error = -EFSCORRUPTED;
2342                         goto out_error;
2343                 }
2344                 trace_xfs_rmap_find_right_neighbor_result(cur,
2345                                 gtrec.rm_startblock, gtrec.rm_blockcount,
2346                                 gtrec.rm_owner, gtrec.rm_offset,
2347                                 gtrec.rm_flags);
2348 
2349                 if (!xfs_rmap_is_mergeable(&gtrec, owner, flags))
2350                         have_gt = 0;
2351         }
2352 
2353         if (have_lt &&
2354             ltrec.rm_startblock + ltrec.rm_blockcount == bno &&
2355             ltrec.rm_offset + ltrec.rm_blockcount == offset) {
2356                 /*
2357                  * Left edge contiguous, merge into left record.
2358                  *
2359                  *       ltbno     ltlen
2360                  * orig:   |ooooooooo|
2361                  * adding:           |aaaaaaaaa|
2362                  * result: |rrrrrrrrrrrrrrrrrrr|
2363                  *                  bno       len
2364                  */
2365                 ltrec.rm_blockcount += len;
2366                 if (have_gt &&
2367                     bno + len == gtrec.rm_startblock &&
2368                     offset + len == gtrec.rm_offset) {
2369                         /*
2370                          * Right edge also contiguous, delete right record
2371                          * and merge into left record.
2372                          *
2373                          *       ltbno     ltlen    gtbno     gtlen
2374                          * orig:   |ooooooooo|         |ooooooooo|
2375                          * adding:           |aaaaaaaaa|
2376                          * result: |rrrrrrrrrrrrrrrrrrrrrrrrrrrrr|
2377                          */
2378                         ltrec.rm_blockcount += gtrec.rm_blockcount;
2379                         error = xfs_rmap_delete(cur, gtrec.rm_startblock,
2380                                         gtrec.rm_blockcount, gtrec.rm_owner,
2381                                         gtrec.rm_offset, gtrec.rm_flags);
2382                         if (error)
2383                                 goto out_error;
2384                 }
2385 
2386                 /* Point the cursor back to the left record and update. */
2387                 error = xfs_rmap_lookup_eq(cur, ltrec.rm_startblock,
2388                                 ltrec.rm_blockcount, ltrec.rm_owner,
2389                                 ltrec.rm_offset, ltrec.rm_flags, &i);
2390                 if (error)
2391                         goto out_error;
2392                 if (XFS_IS_CORRUPT(mp, i != 1)) {
2393                         xfs_btree_mark_sick(cur);
2394                         error = -EFSCORRUPTED;
2395                         goto out_error;
2396                 }
2397 
2398                 error = xfs_rmap_update(cur, &ltrec);
2399                 if (error)
2400                         goto out_error;
2401         } else if (have_gt &&
2402                    bno + len == gtrec.rm_startblock &&
2403                    offset + len == gtrec.rm_offset) {
2404                 /*
2405                  * Right edge contiguous, merge into right record.
2406                  *
2407                  *                 gtbno     gtlen
2408                  * Orig:             |ooooooooo|
2409                  * adding: |aaaaaaaaa|
2410                  * Result: |rrrrrrrrrrrrrrrrrrr|
2411                  *        bno       len
2412                  */
2413                 /* Delete the old record. */
2414                 error = xfs_rmap_delete(cur, gtrec.rm_startblock,
2415                                 gtrec.rm_blockcount, gtrec.rm_owner,
2416                                 gtrec.rm_offset, gtrec.rm_flags);
2417                 if (error)
2418                         goto out_error;
2419 
2420                 /* Move the start and re-add it. */
2421                 gtrec.rm_startblock = bno;
2422                 gtrec.rm_blockcount += len;
2423                 gtrec.rm_offset = offset;
2424                 error = xfs_rmap_insert(cur, gtrec.rm_startblock,
2425                                 gtrec.rm_blockcount, gtrec.rm_owner,
2426                                 gtrec.rm_offset, gtrec.rm_flags);
2427                 if (error)
2428                         goto out_error;
2429         } else {
2430                 /*
2431                  * No contiguous edge with identical owner, insert
2432                  * new record at current cursor position.
2433                  */
2434                 error = xfs_rmap_insert(cur, bno, len, owner, offset, flags);
2435                 if (error)
2436                         goto out_error;
2437         }
2438 
2439         trace_xfs_rmap_map_done(cur, bno, len, unwritten, oinfo);
2440 out_error:
2441         if (error)
2442                 trace_xfs_rmap_map_error(cur, error, _RET_IP_);
2443         return error;
2444 }
2445 
2446 /* Insert a raw rmap into the rmapbt. */
2447 int
2448 xfs_rmap_map_raw(
2449         struct xfs_btree_cur    *cur,
2450         struct xfs_rmap_irec    *rmap)
2451 {
2452         struct xfs_owner_info   oinfo;
2453 
2454         xfs_owner_info_pack(&oinfo, rmap->rm_owner, rmap->rm_offset,
2455                         rmap->rm_flags);
2456 
2457         if ((rmap->rm_flags & (XFS_RMAP_ATTR_FORK | XFS_RMAP_BMBT_BLOCK |
2458                                XFS_RMAP_UNWRITTEN)) ||
2459             XFS_RMAP_NON_INODE_OWNER(rmap->rm_owner))
2460                 return xfs_rmap_map(cur, rmap->rm_startblock,
2461                                 rmap->rm_blockcount,
2462                                 rmap->rm_flags & XFS_RMAP_UNWRITTEN,
2463                                 &oinfo);
2464 
2465         return xfs_rmap_map_shared(cur, rmap->rm_startblock,
2466                         rmap->rm_blockcount,
2467                         rmap->rm_flags & XFS_RMAP_UNWRITTEN,
2468                         &oinfo);
2469 }
2470 
2471 struct xfs_rmap_query_range_info {
2472         xfs_rmap_query_range_fn fn;
2473         void                            *priv;
2474 };
2475 
2476 /* Format btree record and pass to our callback. */
2477 STATIC int
2478 xfs_rmap_query_range_helper(
2479         struct xfs_btree_cur            *cur,
2480         const union xfs_btree_rec       *rec,
2481         void                            *priv)
2482 {
2483         struct xfs_rmap_query_range_info        *query = priv;
2484         struct xfs_rmap_irec                    irec;
2485         xfs_failaddr_t                          fa;
2486 
2487         fa = xfs_rmap_btrec_to_irec(rec, &irec);
2488         if (!fa)
2489                 fa = xfs_rmap_check_btrec(cur, &irec);
2490         if (fa)
2491                 return xfs_rmap_complain_bad_rec(cur, fa, &irec);
2492 
2493         return query->fn(cur, &irec, query->priv);
2494 }
2495 
2496 /* Find all rmaps between two keys. */
2497 int
2498 xfs_rmap_query_range(
2499         struct xfs_btree_cur                    *cur,
2500         const struct xfs_rmap_irec              *low_rec,
2501         const struct xfs_rmap_irec              *high_rec,
2502         xfs_rmap_query_range_fn                 fn,
2503         void                                    *priv)
2504 {
2505         union xfs_btree_irec                    low_brec = { .r = *low_rec };
2506         union xfs_btree_irec                    high_brec = { .r = *high_rec };
2507         struct xfs_rmap_query_range_info        query = { .priv = priv, .fn = fn };
2508 
2509         return xfs_btree_query_range(cur, &low_brec, &high_brec,
2510                         xfs_rmap_query_range_helper, &query);
2511 }
2512 
2513 /* Find all rmaps. */
2514 int
2515 xfs_rmap_query_all(
2516         struct xfs_btree_cur                    *cur,
2517         xfs_rmap_query_range_fn                 fn,
2518         void                                    *priv)
2519 {
2520         struct xfs_rmap_query_range_info        query;
2521 
2522         query.priv = priv;
2523         query.fn = fn;
2524         return xfs_btree_query_all(cur, xfs_rmap_query_range_helper, &query);
2525 }
2526 
2527 /* Commit an rmap operation into the ondisk tree. */
2528 int
2529 __xfs_rmap_finish_intent(
2530         struct xfs_btree_cur            *rcur,
2531         enum xfs_rmap_intent_type       op,
2532         xfs_agblock_t                   bno,
2533         xfs_extlen_t                    len,
2534         const struct xfs_owner_info     *oinfo,
2535         bool                            unwritten)
2536 {
2537         switch (op) {
2538         case XFS_RMAP_ALLOC:
2539         case XFS_RMAP_MAP:
2540                 return xfs_rmap_map(rcur, bno, len, unwritten, oinfo);
2541         case XFS_RMAP_MAP_SHARED:
2542                 return xfs_rmap_map_shared(rcur, bno, len, unwritten, oinfo);
2543         case XFS_RMAP_FREE:
2544         case XFS_RMAP_UNMAP:
2545                 return xfs_rmap_unmap(rcur, bno, len, unwritten, oinfo);
2546         case XFS_RMAP_UNMAP_SHARED:
2547                 return xfs_rmap_unmap_shared(rcur, bno, len, unwritten, oinfo);
2548         case XFS_RMAP_CONVERT:
2549                 return xfs_rmap_convert(rcur, bno, len, !unwritten, oinfo);
2550         case XFS_RMAP_CONVERT_SHARED:
2551                 return xfs_rmap_convert_shared(rcur, bno, len, !unwritten,
2552                                 oinfo);
2553         default:
2554                 ASSERT(0);
2555                 return -EFSCORRUPTED;
2556         }
2557 }
2558 
2559 /*
2560  * Process one of the deferred rmap operations.  We pass back the
2561  * btree cursor to maintain our lock on the rmapbt between calls.
2562  * This saves time and eliminates a buffer deadlock between the
2563  * superblock and the AGF because we'll always grab them in the same
2564  * order.
2565  */
2566 int
2567 xfs_rmap_finish_one(
2568         struct xfs_trans                *tp,
2569         struct xfs_rmap_intent          *ri,
2570         struct xfs_btree_cur            **pcur)
2571 {
2572         struct xfs_owner_info           oinfo;
2573         struct xfs_mount                *mp = tp->t_mountp;
2574         struct xfs_btree_cur            *rcur = *pcur;
2575         struct xfs_buf                  *agbp = NULL;
2576         xfs_agblock_t                   bno;
2577         bool                            unwritten;
2578         int                             error = 0;
2579 
2580         trace_xfs_rmap_deferred(mp, ri);
2581 
2582         if (XFS_TEST_ERROR(false, mp, XFS_ERRTAG_RMAP_FINISH_ONE))
2583                 return -EIO;
2584 
2585         /*
2586          * If we haven't gotten a cursor or the cursor AG doesn't match
2587          * the startblock, get one now.
2588          */
2589         if (rcur != NULL && rcur->bc_ag.pag != ri->ri_pag) {
2590                 xfs_btree_del_cursor(rcur, 0);
2591                 rcur = NULL;
2592                 *pcur = NULL;
2593         }
2594         if (rcur == NULL) {
2595                 /*
2596                  * Refresh the freelist before we start changing the
2597                  * rmapbt, because a shape change could cause us to
2598                  * allocate blocks.
2599                  */
2600                 error = xfs_free_extent_fix_freelist(tp, ri->ri_pag, &agbp);
2601                 if (error) {
2602                         xfs_ag_mark_sick(ri->ri_pag, XFS_SICK_AG_AGFL);
2603                         return error;
2604                 }
2605                 if (XFS_IS_CORRUPT(tp->t_mountp, !agbp)) {
2606                         xfs_ag_mark_sick(ri->ri_pag, XFS_SICK_AG_AGFL);
2607                         return -EFSCORRUPTED;
2608                 }
2609 
2610                 *pcur = rcur = xfs_rmapbt_init_cursor(mp, tp, agbp, ri->ri_pag);
2611         }
2612 
2613         xfs_rmap_ino_owner(&oinfo, ri->ri_owner, ri->ri_whichfork,
2614                         ri->ri_bmap.br_startoff);
2615         unwritten = ri->ri_bmap.br_state == XFS_EXT_UNWRITTEN;
2616         bno = XFS_FSB_TO_AGBNO(rcur->bc_mp, ri->ri_bmap.br_startblock);
2617 
2618         error = __xfs_rmap_finish_intent(rcur, ri->ri_type, bno,
2619                         ri->ri_bmap.br_blockcount, &oinfo, unwritten);
2620         if (error)
2621                 return error;
2622 
2623         xfs_rmap_update_hook(tp, ri->ri_pag, ri->ri_type, bno,
2624                         ri->ri_bmap.br_blockcount, unwritten, &oinfo);
2625         return 0;
2626 }
2627 
2628 /*
2629  * Don't defer an rmap if we aren't an rmap filesystem.
2630  */
2631 static bool
2632 xfs_rmap_update_is_needed(
2633         struct xfs_mount        *mp,
2634         int                     whichfork)
2635 {
2636         return xfs_has_rmapbt(mp) && whichfork != XFS_COW_FORK;
2637 }
2638 
2639 /*
2640  * Record a rmap intent; the list is kept sorted first by AG and then by
2641  * increasing age.
2642  */
2643 static void
2644 __xfs_rmap_add(
2645         struct xfs_trans                *tp,
2646         enum xfs_rmap_intent_type       type,
2647         uint64_t                        owner,
2648         int                             whichfork,
2649         struct xfs_bmbt_irec            *bmap)
2650 {
2651         struct xfs_rmap_intent          *ri;
2652 
2653         ri = kmem_cache_alloc(xfs_rmap_intent_cache, GFP_KERNEL | __GFP_NOFAIL);
2654         INIT_LIST_HEAD(&ri->ri_list);
2655         ri->ri_type = type;
2656         ri->ri_owner = owner;
2657         ri->ri_whichfork = whichfork;
2658         ri->ri_bmap = *bmap;
2659 
2660         xfs_rmap_defer_add(tp, ri);
2661 }
2662 
2663 /* Map an extent into a file. */
2664 void
2665 xfs_rmap_map_extent(
2666         struct xfs_trans        *tp,
2667         struct xfs_inode        *ip,
2668         int                     whichfork,
2669         struct xfs_bmbt_irec    *PREV)
2670 {
2671         enum xfs_rmap_intent_type type = XFS_RMAP_MAP;
2672 
2673         if (!xfs_rmap_update_is_needed(tp->t_mountp, whichfork))
2674                 return;
2675 
2676         if (whichfork != XFS_ATTR_FORK && xfs_is_reflink_inode(ip))
2677                 type = XFS_RMAP_MAP_SHARED;
2678 
2679         __xfs_rmap_add(tp, type, ip->i_ino, whichfork, PREV);
2680 }
2681 
2682 /* Unmap an extent out of a file. */
2683 void
2684 xfs_rmap_unmap_extent(
2685         struct xfs_trans        *tp,
2686         struct xfs_inode        *ip,
2687         int                     whichfork,
2688         struct xfs_bmbt_irec    *PREV)
2689 {
2690         enum xfs_rmap_intent_type type = XFS_RMAP_UNMAP;
2691 
2692         if (!xfs_rmap_update_is_needed(tp->t_mountp, whichfork))
2693                 return;
2694 
2695         if (whichfork != XFS_ATTR_FORK && xfs_is_reflink_inode(ip))
2696                 type = XFS_RMAP_UNMAP_SHARED;
2697 
2698         __xfs_rmap_add(tp, type, ip->i_ino, whichfork, PREV);
2699 }
2700 
2701 /*
2702  * Convert a data fork extent from unwritten to real or vice versa.
2703  *
2704  * Note that tp can be NULL here as no transaction is used for COW fork
2705  * unwritten conversion.
2706  */
2707 void
2708 xfs_rmap_convert_extent(
2709         struct xfs_mount        *mp,
2710         struct xfs_trans        *tp,
2711         struct xfs_inode        *ip,
2712         int                     whichfork,
2713         struct xfs_bmbt_irec    *PREV)
2714 {
2715         enum xfs_rmap_intent_type type = XFS_RMAP_CONVERT;
2716 
2717         if (!xfs_rmap_update_is_needed(mp, whichfork))
2718                 return;
2719 
2720         if (whichfork != XFS_ATTR_FORK && xfs_is_reflink_inode(ip))
2721                 type = XFS_RMAP_CONVERT_SHARED;
2722 
2723         __xfs_rmap_add(tp, type, ip->i_ino, whichfork, PREV);
2724 }
2725 
2726 /* Schedule the creation of an rmap for non-file data. */
2727 void
2728 xfs_rmap_alloc_extent(
2729         struct xfs_trans        *tp,
2730         xfs_agnumber_t          agno,
2731         xfs_agblock_t           bno,
2732         xfs_extlen_t            len,
2733         uint64_t                owner)
2734 {
2735         struct xfs_bmbt_irec    bmap;
2736 
2737         if (!xfs_rmap_update_is_needed(tp->t_mountp, XFS_DATA_FORK))
2738                 return;
2739 
2740         bmap.br_startblock = XFS_AGB_TO_FSB(tp->t_mountp, agno, bno);
2741         bmap.br_blockcount = len;
2742         bmap.br_startoff = 0;
2743         bmap.br_state = XFS_EXT_NORM;
2744 
2745         __xfs_rmap_add(tp, XFS_RMAP_ALLOC, owner, XFS_DATA_FORK, &bmap);
2746 }
2747 
2748 /* Schedule the deletion of an rmap for non-file data. */
2749 void
2750 xfs_rmap_free_extent(
2751         struct xfs_trans        *tp,
2752         xfs_agnumber_t          agno,
2753         xfs_agblock_t           bno,
2754         xfs_extlen_t            len,
2755         uint64_t                owner)
2756 {
2757         struct xfs_bmbt_irec    bmap;
2758 
2759         if (!xfs_rmap_update_is_needed(tp->t_mountp, XFS_DATA_FORK))
2760                 return;
2761 
2762         bmap.br_startblock = XFS_AGB_TO_FSB(tp->t_mountp, agno, bno);
2763         bmap.br_blockcount = len;
2764         bmap.br_startoff = 0;
2765         bmap.br_state = XFS_EXT_NORM;
2766 
2767         __xfs_rmap_add(tp, XFS_RMAP_FREE, owner, XFS_DATA_FORK, &bmap);
2768 }
2769 
2770 /* Compare rmap records.  Returns -1 if a < b, 1 if a > b, and 0 if equal. */
2771 int
2772 xfs_rmap_compare(
2773         const struct xfs_rmap_irec      *a,
2774         const struct xfs_rmap_irec      *b)
2775 {
2776         __u64                           oa;
2777         __u64                           ob;
2778 
2779         oa = xfs_rmap_irec_offset_pack(a);
2780         ob = xfs_rmap_irec_offset_pack(b);
2781 
2782         if (a->rm_startblock < b->rm_startblock)
2783                 return -1;
2784         else if (a->rm_startblock > b->rm_startblock)
2785                 return 1;
2786         else if (a->rm_owner < b->rm_owner)
2787                 return -1;
2788         else if (a->rm_owner > b->rm_owner)
2789                 return 1;
2790         else if (oa < ob)
2791                 return -1;
2792         else if (oa > ob)
2793                 return 1;
2794         else
2795                 return 0;
2796 }
2797 
2798 /*
2799  * Scan the physical storage part of the keyspace of the reverse mapping index
2800  * and tell us if the area has no records, is fully mapped by records, or is
2801  * partially filled.
2802  */
2803 int
2804 xfs_rmap_has_records(
2805         struct xfs_btree_cur    *cur,
2806         xfs_agblock_t           bno,
2807         xfs_extlen_t            len,
2808         enum xbtree_recpacking  *outcome)
2809 {
2810         union xfs_btree_key     mask = {
2811                 .rmap.rm_startblock = cpu_to_be32(-1U),
2812         };
2813         union xfs_btree_irec    low;
2814         union xfs_btree_irec    high;
2815 
2816         memset(&low, 0, sizeof(low));
2817         low.r.rm_startblock = bno;
2818         memset(&high, 0xFF, sizeof(high));
2819         high.r.rm_startblock = bno + len - 1;
2820 
2821         return xfs_btree_has_records(cur, &low, &high, &mask, outcome);
2822 }
2823 
2824 struct xfs_rmap_ownercount {
2825         /* Owner that we're looking for. */
2826         struct xfs_rmap_irec    good;
2827 
2828         /* rmap search keys */
2829         struct xfs_rmap_irec    low;
2830         struct xfs_rmap_irec    high;
2831 
2832         struct xfs_rmap_matches *results;
2833 
2834         /* Stop early if we find a nonmatch? */
2835         bool                    stop_on_nonmatch;
2836 };
2837 
2838 /* Does this rmap represent space that can have multiple owners? */
2839 static inline bool
2840 xfs_rmap_shareable(
2841         struct xfs_mount                *mp,
2842         const struct xfs_rmap_irec      *rmap)
2843 {
2844         if (!xfs_has_reflink(mp))
2845                 return false;
2846         if (XFS_RMAP_NON_INODE_OWNER(rmap->rm_owner))
2847                 return false;
2848         if (rmap->rm_flags & (XFS_RMAP_ATTR_FORK |
2849                               XFS_RMAP_BMBT_BLOCK))
2850                 return false;
2851         return true;
2852 }
2853 
2854 static inline void
2855 xfs_rmap_ownercount_init(
2856         struct xfs_rmap_ownercount      *roc,
2857         xfs_agblock_t                   bno,
2858         xfs_extlen_t                    len,
2859         const struct xfs_owner_info     *oinfo,
2860         struct xfs_rmap_matches         *results)
2861 {
2862         memset(roc, 0, sizeof(*roc));
2863         roc->results = results;
2864 
2865         roc->low.rm_startblock = bno;
2866         memset(&roc->high, 0xFF, sizeof(roc->high));
2867         roc->high.rm_startblock = bno + len - 1;
2868 
2869         memset(results, 0, sizeof(*results));
2870         roc->good.rm_startblock = bno;
2871         roc->good.rm_blockcount = len;
2872         roc->good.rm_owner = oinfo->oi_owner;
2873         roc->good.rm_offset = oinfo->oi_offset;
2874         if (oinfo->oi_flags & XFS_OWNER_INFO_ATTR_FORK)
2875                 roc->good.rm_flags |= XFS_RMAP_ATTR_FORK;
2876         if (oinfo->oi_flags & XFS_OWNER_INFO_BMBT_BLOCK)
2877                 roc->good.rm_flags |= XFS_RMAP_BMBT_BLOCK;
2878 }
2879 
2880 /* Figure out if this is a match for the owner. */
2881 STATIC int
2882 xfs_rmap_count_owners_helper(
2883         struct xfs_btree_cur            *cur,
2884         const struct xfs_rmap_irec      *rec,
2885         void                            *priv)
2886 {
2887         struct xfs_rmap_ownercount      *roc = priv;
2888         struct xfs_rmap_irec            check = *rec;
2889         unsigned int                    keyflags;
2890         bool                            filedata;
2891         int64_t                         delta;
2892 
2893         filedata = !XFS_RMAP_NON_INODE_OWNER(check.rm_owner) &&
2894                    !(check.rm_flags & XFS_RMAP_BMBT_BLOCK);
2895 
2896         /* Trim the part of check that comes before the comparison range. */
2897         delta = (int64_t)roc->good.rm_startblock - check.rm_startblock;
2898         if (delta > 0) {
2899                 check.rm_startblock += delta;
2900                 check.rm_blockcount -= delta;
2901                 if (filedata)
2902                         check.rm_offset += delta;
2903         }
2904 
2905         /* Trim the part of check that comes after the comparison range. */
2906         delta = (check.rm_startblock + check.rm_blockcount) -
2907                 (roc->good.rm_startblock + roc->good.rm_blockcount);
2908         if (delta > 0)
2909                 check.rm_blockcount -= delta;
2910 
2911         /* Don't care about unwritten status for establishing ownership. */
2912         keyflags = check.rm_flags & (XFS_RMAP_ATTR_FORK | XFS_RMAP_BMBT_BLOCK);
2913 
2914         if (check.rm_startblock == roc->good.rm_startblock &&
2915             check.rm_blockcount == roc->good.rm_blockcount &&
2916             check.rm_owner      == roc->good.rm_owner &&
2917             check.rm_offset     == roc->good.rm_offset &&
2918             keyflags            == roc->good.rm_flags) {
2919                 roc->results->matches++;
2920         } else {
2921                 roc->results->non_owner_matches++;
2922                 if (xfs_rmap_shareable(cur->bc_mp, &roc->good) ^
2923                     xfs_rmap_shareable(cur->bc_mp, &check))
2924                         roc->results->bad_non_owner_matches++;
2925         }
2926 
2927         if (roc->results->non_owner_matches && roc->stop_on_nonmatch)
2928                 return -ECANCELED;
2929 
2930         return 0;
2931 }
2932 
2933 /* Count the number of owners and non-owners of this range of blocks. */
2934 int
2935 xfs_rmap_count_owners(
2936         struct xfs_btree_cur            *cur,
2937         xfs_agblock_t                   bno,
2938         xfs_extlen_t                    len,
2939         const struct xfs_owner_info     *oinfo,
2940         struct xfs_rmap_matches         *results)
2941 {
2942         struct xfs_rmap_ownercount      roc;
2943         int                             error;
2944 
2945         xfs_rmap_ownercount_init(&roc, bno, len, oinfo, results);
2946         error = xfs_rmap_query_range(cur, &roc.low, &roc.high,
2947                         xfs_rmap_count_owners_helper, &roc);
2948         if (error)
2949                 return error;
2950 
2951         /*
2952          * There can't be any non-owner rmaps that conflict with the given
2953          * owner if we didn't find any rmaps matching the owner.
2954          */
2955         if (!results->matches)
2956                 results->bad_non_owner_matches = 0;
2957 
2958         return 0;
2959 }
2960 
2961 /*
2962  * Given an extent and some owner info, can we find records overlapping
2963  * the extent whose owner info does not match the given owner?
2964  */
2965 int
2966 xfs_rmap_has_other_keys(
2967         struct xfs_btree_cur            *cur,
2968         xfs_agblock_t                   bno,
2969         xfs_extlen_t                    len,
2970         const struct xfs_owner_info     *oinfo,
2971         bool                            *has_other)
2972 {
2973         struct xfs_rmap_matches         res;
2974         struct xfs_rmap_ownercount      roc;
2975         int                             error;
2976 
2977         xfs_rmap_ownercount_init(&roc, bno, len, oinfo, &res);
2978         roc.stop_on_nonmatch = true;
2979 
2980         error = xfs_rmap_query_range(cur, &roc.low, &roc.high,
2981                         xfs_rmap_count_owners_helper, &roc);
2982         if (error == -ECANCELED) {
2983                 *has_other = true;
2984                 return 0;
2985         }
2986         if (error)
2987                 return error;
2988 
2989         *has_other = false;
2990         return 0;
2991 }
2992 
2993 const struct xfs_owner_info XFS_RMAP_OINFO_SKIP_UPDATE = {
2994         .oi_owner = XFS_RMAP_OWN_NULL,
2995 };
2996 const struct xfs_owner_info XFS_RMAP_OINFO_ANY_OWNER = {
2997         .oi_owner = XFS_RMAP_OWN_UNKNOWN,
2998 };
2999 const struct xfs_owner_info XFS_RMAP_OINFO_FS = {
3000         .oi_owner = XFS_RMAP_OWN_FS,
3001 };
3002 const struct xfs_owner_info XFS_RMAP_OINFO_LOG = {
3003         .oi_owner = XFS_RMAP_OWN_LOG,
3004 };
3005 const struct xfs_owner_info XFS_RMAP_OINFO_AG = {
3006         .oi_owner = XFS_RMAP_OWN_AG,
3007 };
3008 const struct xfs_owner_info XFS_RMAP_OINFO_INOBT = {
3009         .oi_owner = XFS_RMAP_OWN_INOBT,
3010 };
3011 const struct xfs_owner_info XFS_RMAP_OINFO_INODES = {
3012         .oi_owner = XFS_RMAP_OWN_INODES,
3013 };
3014 const struct xfs_owner_info XFS_RMAP_OINFO_REFC = {
3015         .oi_owner = XFS_RMAP_OWN_REFC,
3016 };
3017 const struct xfs_owner_info XFS_RMAP_OINFO_COW = {
3018         .oi_owner = XFS_RMAP_OWN_COW,
3019 };
3020 
3021 int __init
3022 xfs_rmap_intent_init_cache(void)
3023 {
3024         xfs_rmap_intent_cache = kmem_cache_create("xfs_rmap_intent",
3025                         sizeof(struct xfs_rmap_intent),
3026                         0, 0, NULL);
3027 
3028         return xfs_rmap_intent_cache != NULL ? 0 : -ENOMEM;
3029 }
3030 
3031 void
3032 xfs_rmap_intent_destroy_cache(void)
3033 {
3034         kmem_cache_destroy(xfs_rmap_intent_cache);
3035         xfs_rmap_intent_cache = NULL;
3036 }
3037 

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

kernel.org | git.kernel.org | LWN.net | Project Home | 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.

sflogo.php