xref: /openbmc/linux/fs/xfs/libxfs/xfs_refcount.c (revision bdf28630)
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