1bdf28630SDarrick J. Wong /* 2bdf28630SDarrick J. Wong * Copyright (C) 2016 Oracle. All Rights Reserved. 3bdf28630SDarrick J. Wong * 4bdf28630SDarrick J. Wong * Author: Darrick J. Wong <darrick.wong@oracle.com> 5bdf28630SDarrick J. Wong * 6bdf28630SDarrick J. Wong * This program is free software; you can redistribute it and/or 7bdf28630SDarrick J. Wong * modify it under the terms of the GNU General Public License 8bdf28630SDarrick J. Wong * as published by the Free Software Foundation; either version 2 9bdf28630SDarrick J. Wong * of the License, or (at your option) any later version. 10bdf28630SDarrick J. Wong * 11bdf28630SDarrick J. Wong * This program is distributed in the hope that it would be useful, 12bdf28630SDarrick J. Wong * but WITHOUT ANY WARRANTY; without even the implied warranty of 13bdf28630SDarrick J. Wong * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14bdf28630SDarrick J. Wong * GNU General Public License for more details. 15bdf28630SDarrick J. Wong * 16bdf28630SDarrick J. Wong * You should have received a copy of the GNU General Public License 17bdf28630SDarrick J. Wong * along with this program; if not, write the Free Software Foundation, 18bdf28630SDarrick J. Wong * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. 19bdf28630SDarrick J. Wong */ 20bdf28630SDarrick J. Wong #include "xfs.h" 21bdf28630SDarrick J. Wong #include "xfs_fs.h" 22bdf28630SDarrick J. Wong #include "xfs_shared.h" 23bdf28630SDarrick J. Wong #include "xfs_format.h" 24bdf28630SDarrick J. Wong #include "xfs_log_format.h" 25bdf28630SDarrick J. Wong #include "xfs_trans_resv.h" 26bdf28630SDarrick J. Wong #include "xfs_sb.h" 27bdf28630SDarrick J. Wong #include "xfs_mount.h" 28bdf28630SDarrick J. Wong #include "xfs_defer.h" 29bdf28630SDarrick J. Wong #include "xfs_btree.h" 30bdf28630SDarrick J. Wong #include "xfs_bmap.h" 31bdf28630SDarrick J. Wong #include "xfs_refcount_btree.h" 32bdf28630SDarrick J. Wong #include "xfs_alloc.h" 33bdf28630SDarrick J. Wong #include "xfs_error.h" 34bdf28630SDarrick J. Wong #include "xfs_trace.h" 35bdf28630SDarrick J. Wong #include "xfs_cksum.h" 36bdf28630SDarrick J. Wong #include "xfs_trans.h" 37bdf28630SDarrick J. Wong #include "xfs_bit.h" 38bdf28630SDarrick J. Wong #include "xfs_refcount.h" 39bdf28630SDarrick J. Wong 40bdf28630SDarrick J. Wong /* 41bdf28630SDarrick J. Wong * Look up the first record less than or equal to [bno, len] in the btree 42bdf28630SDarrick J. Wong * given by cur. 43bdf28630SDarrick J. Wong */ 44bdf28630SDarrick J. Wong int 45bdf28630SDarrick J. Wong xfs_refcount_lookup_le( 46bdf28630SDarrick J. Wong struct xfs_btree_cur *cur, 47bdf28630SDarrick J. Wong xfs_agblock_t bno, 48bdf28630SDarrick J. Wong int *stat) 49bdf28630SDarrick J. Wong { 50bdf28630SDarrick J. Wong trace_xfs_refcount_lookup(cur->bc_mp, cur->bc_private.a.agno, bno, 51bdf28630SDarrick J. Wong XFS_LOOKUP_LE); 52bdf28630SDarrick J. Wong cur->bc_rec.rc.rc_startblock = bno; 53bdf28630SDarrick J. Wong cur->bc_rec.rc.rc_blockcount = 0; 54bdf28630SDarrick J. Wong return xfs_btree_lookup(cur, XFS_LOOKUP_LE, stat); 55bdf28630SDarrick J. Wong } 56bdf28630SDarrick J. Wong 57bdf28630SDarrick J. Wong /* 58bdf28630SDarrick J. Wong * Look up the first record greater than or equal to [bno, len] in the btree 59bdf28630SDarrick J. Wong * given by cur. 60bdf28630SDarrick J. Wong */ 61bdf28630SDarrick J. Wong int 62bdf28630SDarrick J. Wong xfs_refcount_lookup_ge( 63bdf28630SDarrick J. Wong struct xfs_btree_cur *cur, 64bdf28630SDarrick J. Wong xfs_agblock_t bno, 65bdf28630SDarrick J. Wong int *stat) 66bdf28630SDarrick J. Wong { 67bdf28630SDarrick J. Wong trace_xfs_refcount_lookup(cur->bc_mp, cur->bc_private.a.agno, bno, 68bdf28630SDarrick J. Wong XFS_LOOKUP_GE); 69bdf28630SDarrick J. Wong cur->bc_rec.rc.rc_startblock = bno; 70bdf28630SDarrick J. Wong cur->bc_rec.rc.rc_blockcount = 0; 71bdf28630SDarrick J. Wong return xfs_btree_lookup(cur, XFS_LOOKUP_GE, stat); 72bdf28630SDarrick J. Wong } 73bdf28630SDarrick J. Wong 74bdf28630SDarrick J. Wong /* 75bdf28630SDarrick J. Wong * Get the data from the pointed-to record. 76bdf28630SDarrick J. Wong */ 77bdf28630SDarrick J. Wong int 78bdf28630SDarrick J. Wong xfs_refcount_get_rec( 79bdf28630SDarrick J. Wong struct xfs_btree_cur *cur, 80bdf28630SDarrick J. Wong struct xfs_refcount_irec *irec, 81bdf28630SDarrick J. Wong int *stat) 82bdf28630SDarrick J. Wong { 83bdf28630SDarrick J. Wong union xfs_btree_rec *rec; 84bdf28630SDarrick J. Wong int error; 85bdf28630SDarrick J. Wong 86bdf28630SDarrick J. Wong error = xfs_btree_get_rec(cur, &rec, stat); 87bdf28630SDarrick J. Wong if (!error && *stat == 1) { 88bdf28630SDarrick J. Wong irec->rc_startblock = be32_to_cpu(rec->refc.rc_startblock); 89bdf28630SDarrick J. Wong irec->rc_blockcount = be32_to_cpu(rec->refc.rc_blockcount); 90bdf28630SDarrick J. Wong irec->rc_refcount = be32_to_cpu(rec->refc.rc_refcount); 91bdf28630SDarrick J. Wong trace_xfs_refcount_get(cur->bc_mp, cur->bc_private.a.agno, 92bdf28630SDarrick J. Wong irec); 93bdf28630SDarrick J. Wong } 94bdf28630SDarrick J. Wong return error; 95bdf28630SDarrick J. Wong } 96bdf28630SDarrick J. Wong 97bdf28630SDarrick J. Wong /* 98bdf28630SDarrick J. Wong * Update the record referred to by cur to the value given 99bdf28630SDarrick J. Wong * by [bno, len, refcount]. 100bdf28630SDarrick J. Wong * This either works (return 0) or gets an EFSCORRUPTED error. 101bdf28630SDarrick J. Wong */ 102bdf28630SDarrick J. Wong STATIC int 103bdf28630SDarrick J. Wong xfs_refcount_update( 104bdf28630SDarrick J. Wong struct xfs_btree_cur *cur, 105bdf28630SDarrick J. Wong struct xfs_refcount_irec *irec) 106bdf28630SDarrick J. Wong { 107bdf28630SDarrick J. Wong union xfs_btree_rec rec; 108bdf28630SDarrick J. Wong int error; 109bdf28630SDarrick J. Wong 110bdf28630SDarrick J. Wong trace_xfs_refcount_update(cur->bc_mp, cur->bc_private.a.agno, irec); 111bdf28630SDarrick J. Wong rec.refc.rc_startblock = cpu_to_be32(irec->rc_startblock); 112bdf28630SDarrick J. Wong rec.refc.rc_blockcount = cpu_to_be32(irec->rc_blockcount); 113bdf28630SDarrick J. Wong rec.refc.rc_refcount = cpu_to_be32(irec->rc_refcount); 114bdf28630SDarrick J. Wong error = xfs_btree_update(cur, &rec); 115bdf28630SDarrick J. Wong if (error) 116bdf28630SDarrick J. Wong trace_xfs_refcount_update_error(cur->bc_mp, 117bdf28630SDarrick J. Wong cur->bc_private.a.agno, error, _RET_IP_); 118bdf28630SDarrick J. Wong return error; 119bdf28630SDarrick J. Wong } 120bdf28630SDarrick J. Wong 121bdf28630SDarrick J. Wong /* 122bdf28630SDarrick J. Wong * Insert the record referred to by cur to the value given 123bdf28630SDarrick J. Wong * by [bno, len, refcount]. 124bdf28630SDarrick J. Wong * This either works (return 0) or gets an EFSCORRUPTED error. 125bdf28630SDarrick J. Wong */ 126bdf28630SDarrick J. Wong STATIC int 127bdf28630SDarrick J. Wong xfs_refcount_insert( 128bdf28630SDarrick J. Wong struct xfs_btree_cur *cur, 129bdf28630SDarrick J. Wong struct xfs_refcount_irec *irec, 130bdf28630SDarrick J. Wong int *i) 131bdf28630SDarrick J. Wong { 132bdf28630SDarrick J. Wong int error; 133bdf28630SDarrick J. Wong 134bdf28630SDarrick J. Wong trace_xfs_refcount_insert(cur->bc_mp, cur->bc_private.a.agno, irec); 135bdf28630SDarrick J. Wong cur->bc_rec.rc.rc_startblock = irec->rc_startblock; 136bdf28630SDarrick J. Wong cur->bc_rec.rc.rc_blockcount = irec->rc_blockcount; 137bdf28630SDarrick J. Wong cur->bc_rec.rc.rc_refcount = irec->rc_refcount; 138bdf28630SDarrick J. Wong error = xfs_btree_insert(cur, i); 139bdf28630SDarrick J. Wong XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, *i == 1, out_error); 140bdf28630SDarrick J. Wong out_error: 141bdf28630SDarrick J. Wong if (error) 142bdf28630SDarrick J. Wong trace_xfs_refcount_insert_error(cur->bc_mp, 143bdf28630SDarrick J. Wong cur->bc_private.a.agno, error, _RET_IP_); 144bdf28630SDarrick J. Wong return error; 145bdf28630SDarrick J. Wong } 146bdf28630SDarrick J. Wong 147bdf28630SDarrick J. Wong /* 148bdf28630SDarrick J. Wong * Remove the record referred to by cur, then set the pointer to the spot 149bdf28630SDarrick J. Wong * where the record could be re-inserted, in case we want to increment or 150bdf28630SDarrick J. Wong * decrement the cursor. 151bdf28630SDarrick J. Wong * This either works (return 0) or gets an EFSCORRUPTED error. 152bdf28630SDarrick J. Wong */ 153bdf28630SDarrick J. Wong STATIC int 154bdf28630SDarrick J. Wong xfs_refcount_delete( 155bdf28630SDarrick J. Wong struct xfs_btree_cur *cur, 156bdf28630SDarrick J. Wong int *i) 157bdf28630SDarrick J. Wong { 158bdf28630SDarrick J. Wong struct xfs_refcount_irec irec; 159bdf28630SDarrick J. Wong int found_rec; 160bdf28630SDarrick J. Wong int error; 161bdf28630SDarrick J. Wong 162bdf28630SDarrick J. Wong error = xfs_refcount_get_rec(cur, &irec, &found_rec); 163bdf28630SDarrick J. Wong if (error) 164bdf28630SDarrick J. Wong goto out_error; 165bdf28630SDarrick J. Wong XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, found_rec == 1, out_error); 166bdf28630SDarrick J. Wong trace_xfs_refcount_delete(cur->bc_mp, cur->bc_private.a.agno, &irec); 167bdf28630SDarrick J. Wong error = xfs_btree_delete(cur, i); 168bdf28630SDarrick J. Wong XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, *i == 1, out_error); 169bdf28630SDarrick J. Wong if (error) 170bdf28630SDarrick J. Wong goto out_error; 171bdf28630SDarrick J. Wong error = xfs_refcount_lookup_ge(cur, irec.rc_startblock, &found_rec); 172bdf28630SDarrick J. Wong out_error: 173bdf28630SDarrick J. Wong if (error) 174bdf28630SDarrick J. Wong trace_xfs_refcount_delete_error(cur->bc_mp, 175bdf28630SDarrick J. Wong cur->bc_private.a.agno, error, _RET_IP_); 176bdf28630SDarrick J. Wong return error; 177bdf28630SDarrick J. Wong } 178