Linux Audio

Check our new training course

Linux BSP upgrade and security maintenance

Need help to get security updates for your Linux BSP?
Loading...
Note: File does not exist in v6.13.7.
  1/*
  2 * Copyright (C) 2016 Oracle.  All Rights Reserved.
  3 *
  4 * Author: Darrick J. Wong <darrick.wong@oracle.com>
  5 *
  6 * This program is free software; you can redistribute it and/or
  7 * modify it under the terms of the GNU General Public License
  8 * as published by the Free Software Foundation; either version 2
  9 * of the License, or (at your option) any later version.
 10 *
 11 * This program is distributed in the hope that it would be useful,
 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 14 * GNU General Public License for more details.
 15 *
 16 * You should have received a copy of the GNU General Public License
 17 * along with this program; if not, write the Free Software Foundation,
 18 * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA.
 19 */
 20#include "xfs.h"
 21#include "xfs_fs.h"
 22#include "xfs_shared.h"
 23#include "xfs_format.h"
 24#include "xfs_log_format.h"
 25#include "xfs_trans_resv.h"
 26#include "xfs_mount.h"
 27#include "xfs_defer.h"
 28#include "xfs_trans.h"
 29#include "xfs_trans_priv.h"
 30#include "xfs_rmap_item.h"
 31#include "xfs_alloc.h"
 32#include "xfs_rmap.h"
 33
 34/* Set the map extent flags for this reverse mapping. */
 35static void
 36xfs_trans_set_rmap_flags(
 37	struct xfs_map_extent		*rmap,
 38	enum xfs_rmap_intent_type	type,
 39	int				whichfork,
 40	xfs_exntst_t			state)
 41{
 42	rmap->me_flags = 0;
 43	if (state == XFS_EXT_UNWRITTEN)
 44		rmap->me_flags |= XFS_RMAP_EXTENT_UNWRITTEN;
 45	if (whichfork == XFS_ATTR_FORK)
 46		rmap->me_flags |= XFS_RMAP_EXTENT_ATTR_FORK;
 47	switch (type) {
 48	case XFS_RMAP_MAP:
 49		rmap->me_flags |= XFS_RMAP_EXTENT_MAP;
 50		break;
 51	case XFS_RMAP_MAP_SHARED:
 52		rmap->me_flags |= XFS_RMAP_EXTENT_MAP_SHARED;
 53		break;
 54	case XFS_RMAP_UNMAP:
 55		rmap->me_flags |= XFS_RMAP_EXTENT_UNMAP;
 56		break;
 57	case XFS_RMAP_UNMAP_SHARED:
 58		rmap->me_flags |= XFS_RMAP_EXTENT_UNMAP_SHARED;
 59		break;
 60	case XFS_RMAP_CONVERT:
 61		rmap->me_flags |= XFS_RMAP_EXTENT_CONVERT;
 62		break;
 63	case XFS_RMAP_CONVERT_SHARED:
 64		rmap->me_flags |= XFS_RMAP_EXTENT_CONVERT_SHARED;
 65		break;
 66	case XFS_RMAP_ALLOC:
 67		rmap->me_flags |= XFS_RMAP_EXTENT_ALLOC;
 68		break;
 69	case XFS_RMAP_FREE:
 70		rmap->me_flags |= XFS_RMAP_EXTENT_FREE;
 71		break;
 72	default:
 73		ASSERT(0);
 74	}
 75}
 76
 77struct xfs_rud_log_item *
 78xfs_trans_get_rud(
 79	struct xfs_trans		*tp,
 80	struct xfs_rui_log_item		*ruip)
 81{
 82	struct xfs_rud_log_item		*rudp;
 83
 84	rudp = xfs_rud_init(tp->t_mountp, ruip);
 85	xfs_trans_add_item(tp, &rudp->rud_item);
 86	return rudp;
 87}
 88
 89/*
 90 * Finish an rmap update and log it to the RUD. Note that the transaction is
 91 * marked dirty regardless of whether the rmap update succeeds or fails to
 92 * support the RUI/RUD lifecycle rules.
 93 */
 94int
 95xfs_trans_log_finish_rmap_update(
 96	struct xfs_trans		*tp,
 97	struct xfs_rud_log_item		*rudp,
 98	enum xfs_rmap_intent_type	type,
 99	uint64_t			owner,
100	int				whichfork,
101	xfs_fileoff_t			startoff,
102	xfs_fsblock_t			startblock,
103	xfs_filblks_t			blockcount,
104	xfs_exntst_t			state,
105	struct xfs_btree_cur		**pcur)
106{
107	int				error;
108
109	error = xfs_rmap_finish_one(tp, type, owner, whichfork, startoff,
110			startblock, blockcount, state, pcur);
111
112	/*
113	 * Mark the transaction dirty, even on error. This ensures the
114	 * transaction is aborted, which:
115	 *
116	 * 1.) releases the RUI and frees the RUD
117	 * 2.) shuts down the filesystem
118	 */
119	tp->t_flags |= XFS_TRANS_DIRTY;
120	rudp->rud_item.li_desc->lid_flags |= XFS_LID_DIRTY;
121
122	return error;
123}
124
125/* Sort rmap intents by AG. */
126static int
127xfs_rmap_update_diff_items(
128	void				*priv,
129	struct list_head		*a,
130	struct list_head		*b)
131{
132	struct xfs_mount		*mp = priv;
133	struct xfs_rmap_intent		*ra;
134	struct xfs_rmap_intent		*rb;
135
136	ra = container_of(a, struct xfs_rmap_intent, ri_list);
137	rb = container_of(b, struct xfs_rmap_intent, ri_list);
138	return  XFS_FSB_TO_AGNO(mp, ra->ri_bmap.br_startblock) -
139		XFS_FSB_TO_AGNO(mp, rb->ri_bmap.br_startblock);
140}
141
142/* Get an RUI. */
143STATIC void *
144xfs_rmap_update_create_intent(
145	struct xfs_trans		*tp,
146	unsigned int			count)
147{
148	struct xfs_rui_log_item		*ruip;
149
150	ASSERT(tp != NULL);
151	ASSERT(count > 0);
152
153	ruip = xfs_rui_init(tp->t_mountp, count);
154	ASSERT(ruip != NULL);
155
156	/*
157	 * Get a log_item_desc to point at the new item.
158	 */
159	xfs_trans_add_item(tp, &ruip->rui_item);
160	return ruip;
161}
162
163/* Log rmap updates in the intent item. */
164STATIC void
165xfs_rmap_update_log_item(
166	struct xfs_trans		*tp,
167	void				*intent,
168	struct list_head		*item)
169{
170	struct xfs_rui_log_item		*ruip = intent;
171	struct xfs_rmap_intent		*rmap;
172	uint				next_extent;
173	struct xfs_map_extent		*map;
174
175	rmap = container_of(item, struct xfs_rmap_intent, ri_list);
176
177	tp->t_flags |= XFS_TRANS_DIRTY;
178	ruip->rui_item.li_desc->lid_flags |= XFS_LID_DIRTY;
179
180	/*
181	 * atomic_inc_return gives us the value after the increment;
182	 * we want to use it as an array index so we need to subtract 1 from
183	 * it.
184	 */
185	next_extent = atomic_inc_return(&ruip->rui_next_extent) - 1;
186	ASSERT(next_extent < ruip->rui_format.rui_nextents);
187	map = &ruip->rui_format.rui_extents[next_extent];
188	map->me_owner = rmap->ri_owner;
189	map->me_startblock = rmap->ri_bmap.br_startblock;
190	map->me_startoff = rmap->ri_bmap.br_startoff;
191	map->me_len = rmap->ri_bmap.br_blockcount;
192	xfs_trans_set_rmap_flags(map, rmap->ri_type, rmap->ri_whichfork,
193			rmap->ri_bmap.br_state);
194}
195
196/* Get an RUD so we can process all the deferred rmap updates. */
197STATIC void *
198xfs_rmap_update_create_done(
199	struct xfs_trans		*tp,
200	void				*intent,
201	unsigned int			count)
202{
203	return xfs_trans_get_rud(tp, intent);
204}
205
206/* Process a deferred rmap update. */
207STATIC int
208xfs_rmap_update_finish_item(
209	struct xfs_trans		*tp,
210	struct xfs_defer_ops		*dop,
211	struct list_head		*item,
212	void				*done_item,
213	void				**state)
214{
215	struct xfs_rmap_intent		*rmap;
216	int				error;
217
218	rmap = container_of(item, struct xfs_rmap_intent, ri_list);
219	error = xfs_trans_log_finish_rmap_update(tp, done_item,
220			rmap->ri_type,
221			rmap->ri_owner, rmap->ri_whichfork,
222			rmap->ri_bmap.br_startoff,
223			rmap->ri_bmap.br_startblock,
224			rmap->ri_bmap.br_blockcount,
225			rmap->ri_bmap.br_state,
226			(struct xfs_btree_cur **)state);
227	kmem_free(rmap);
228	return error;
229}
230
231/* Clean up after processing deferred rmaps. */
232STATIC void
233xfs_rmap_update_finish_cleanup(
234	struct xfs_trans	*tp,
235	void			*state,
236	int			error)
237{
238	struct xfs_btree_cur	*rcur = state;
239
240	xfs_rmap_finish_one_cleanup(tp, rcur, error);
241}
242
243/* Abort all pending RUIs. */
244STATIC void
245xfs_rmap_update_abort_intent(
246	void				*intent)
247{
248	xfs_rui_release(intent);
249}
250
251/* Cancel a deferred rmap update. */
252STATIC void
253xfs_rmap_update_cancel_item(
254	struct list_head		*item)
255{
256	struct xfs_rmap_intent		*rmap;
257
258	rmap = container_of(item, struct xfs_rmap_intent, ri_list);
259	kmem_free(rmap);
260}
261
262static const struct xfs_defer_op_type xfs_rmap_update_defer_type = {
263	.type		= XFS_DEFER_OPS_TYPE_RMAP,
264	.max_items	= XFS_RUI_MAX_FAST_EXTENTS,
265	.diff_items	= xfs_rmap_update_diff_items,
266	.create_intent	= xfs_rmap_update_create_intent,
267	.abort_intent	= xfs_rmap_update_abort_intent,
268	.log_item	= xfs_rmap_update_log_item,
269	.create_done	= xfs_rmap_update_create_done,
270	.finish_item	= xfs_rmap_update_finish_item,
271	.finish_cleanup = xfs_rmap_update_finish_cleanup,
272	.cancel_item	= xfs_rmap_update_cancel_item,
273};
274
275/* Register the deferred op type. */
276void
277xfs_rmap_update_init_defer_op(void)
278{
279	xfs_defer_init_op_type(&xfs_rmap_update_defer_type);
280}