Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v4.14-rc5 280 lines 7.3 kB view raw
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}