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 v5.0-rc1 233 lines 5.7 kB view raw
1// SPDX-License-Identifier: GPL-2.0+ 2/* 3 * Copyright (C) 2016 Oracle. All Rights Reserved. 4 * Author: Darrick J. Wong <darrick.wong@oracle.com> 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_mount.h" 13#include "xfs_defer.h" 14#include "xfs_trans.h" 15#include "xfs_trans_priv.h" 16#include "xfs_bmap_item.h" 17#include "xfs_alloc.h" 18#include "xfs_bmap.h" 19#include "xfs_inode.h" 20#include "xfs_defer.h" 21 22/* 23 * This routine is called to allocate a "bmap update done" 24 * log item. 25 */ 26struct xfs_bud_log_item * 27xfs_trans_get_bud( 28 struct xfs_trans *tp, 29 struct xfs_bui_log_item *buip) 30{ 31 struct xfs_bud_log_item *budp; 32 33 budp = xfs_bud_init(tp->t_mountp, buip); 34 xfs_trans_add_item(tp, &budp->bud_item); 35 return budp; 36} 37 38/* 39 * Finish an bmap update and log it to the BUD. Note that the 40 * transaction is marked dirty regardless of whether the bmap update 41 * succeeds or fails to support the BUI/BUD lifecycle rules. 42 */ 43int 44xfs_trans_log_finish_bmap_update( 45 struct xfs_trans *tp, 46 struct xfs_bud_log_item *budp, 47 enum xfs_bmap_intent_type type, 48 struct xfs_inode *ip, 49 int whichfork, 50 xfs_fileoff_t startoff, 51 xfs_fsblock_t startblock, 52 xfs_filblks_t *blockcount, 53 xfs_exntst_t state) 54{ 55 int error; 56 57 error = xfs_bmap_finish_one(tp, ip, type, whichfork, startoff, 58 startblock, blockcount, state); 59 60 /* 61 * Mark the transaction dirty, even on error. This ensures the 62 * transaction is aborted, which: 63 * 64 * 1.) releases the BUI and frees the BUD 65 * 2.) shuts down the filesystem 66 */ 67 tp->t_flags |= XFS_TRANS_DIRTY; 68 set_bit(XFS_LI_DIRTY, &budp->bud_item.li_flags); 69 70 return error; 71} 72 73/* Sort bmap intents by inode. */ 74static int 75xfs_bmap_update_diff_items( 76 void *priv, 77 struct list_head *a, 78 struct list_head *b) 79{ 80 struct xfs_bmap_intent *ba; 81 struct xfs_bmap_intent *bb; 82 83 ba = container_of(a, struct xfs_bmap_intent, bi_list); 84 bb = container_of(b, struct xfs_bmap_intent, bi_list); 85 return ba->bi_owner->i_ino - bb->bi_owner->i_ino; 86} 87 88/* Get an BUI. */ 89STATIC void * 90xfs_bmap_update_create_intent( 91 struct xfs_trans *tp, 92 unsigned int count) 93{ 94 struct xfs_bui_log_item *buip; 95 96 ASSERT(count == XFS_BUI_MAX_FAST_EXTENTS); 97 ASSERT(tp != NULL); 98 99 buip = xfs_bui_init(tp->t_mountp); 100 ASSERT(buip != NULL); 101 102 /* 103 * Get a log_item_desc to point at the new item. 104 */ 105 xfs_trans_add_item(tp, &buip->bui_item); 106 return buip; 107} 108 109/* Set the map extent flags for this mapping. */ 110static void 111xfs_trans_set_bmap_flags( 112 struct xfs_map_extent *bmap, 113 enum xfs_bmap_intent_type type, 114 int whichfork, 115 xfs_exntst_t state) 116{ 117 bmap->me_flags = 0; 118 switch (type) { 119 case XFS_BMAP_MAP: 120 case XFS_BMAP_UNMAP: 121 bmap->me_flags = type; 122 break; 123 default: 124 ASSERT(0); 125 } 126 if (state == XFS_EXT_UNWRITTEN) 127 bmap->me_flags |= XFS_BMAP_EXTENT_UNWRITTEN; 128 if (whichfork == XFS_ATTR_FORK) 129 bmap->me_flags |= XFS_BMAP_EXTENT_ATTR_FORK; 130} 131 132/* Log bmap updates in the intent item. */ 133STATIC void 134xfs_bmap_update_log_item( 135 struct xfs_trans *tp, 136 void *intent, 137 struct list_head *item) 138{ 139 struct xfs_bui_log_item *buip = intent; 140 struct xfs_bmap_intent *bmap; 141 uint next_extent; 142 struct xfs_map_extent *map; 143 144 bmap = container_of(item, struct xfs_bmap_intent, bi_list); 145 146 tp->t_flags |= XFS_TRANS_DIRTY; 147 set_bit(XFS_LI_DIRTY, &buip->bui_item.li_flags); 148 149 /* 150 * atomic_inc_return gives us the value after the increment; 151 * we want to use it as an array index so we need to subtract 1 from 152 * it. 153 */ 154 next_extent = atomic_inc_return(&buip->bui_next_extent) - 1; 155 ASSERT(next_extent < buip->bui_format.bui_nextents); 156 map = &buip->bui_format.bui_extents[next_extent]; 157 map->me_owner = bmap->bi_owner->i_ino; 158 map->me_startblock = bmap->bi_bmap.br_startblock; 159 map->me_startoff = bmap->bi_bmap.br_startoff; 160 map->me_len = bmap->bi_bmap.br_blockcount; 161 xfs_trans_set_bmap_flags(map, bmap->bi_type, bmap->bi_whichfork, 162 bmap->bi_bmap.br_state); 163} 164 165/* Get an BUD so we can process all the deferred rmap updates. */ 166STATIC void * 167xfs_bmap_update_create_done( 168 struct xfs_trans *tp, 169 void *intent, 170 unsigned int count) 171{ 172 return xfs_trans_get_bud(tp, intent); 173} 174 175/* Process a deferred rmap update. */ 176STATIC int 177xfs_bmap_update_finish_item( 178 struct xfs_trans *tp, 179 struct list_head *item, 180 void *done_item, 181 void **state) 182{ 183 struct xfs_bmap_intent *bmap; 184 xfs_filblks_t count; 185 int error; 186 187 bmap = container_of(item, struct xfs_bmap_intent, bi_list); 188 count = bmap->bi_bmap.br_blockcount; 189 error = xfs_trans_log_finish_bmap_update(tp, done_item, 190 bmap->bi_type, 191 bmap->bi_owner, bmap->bi_whichfork, 192 bmap->bi_bmap.br_startoff, 193 bmap->bi_bmap.br_startblock, 194 &count, 195 bmap->bi_bmap.br_state); 196 if (!error && count > 0) { 197 ASSERT(bmap->bi_type == XFS_BMAP_UNMAP); 198 bmap->bi_bmap.br_blockcount = count; 199 return -EAGAIN; 200 } 201 kmem_free(bmap); 202 return error; 203} 204 205/* Abort all pending BUIs. */ 206STATIC void 207xfs_bmap_update_abort_intent( 208 void *intent) 209{ 210 xfs_bui_release(intent); 211} 212 213/* Cancel a deferred rmap update. */ 214STATIC void 215xfs_bmap_update_cancel_item( 216 struct list_head *item) 217{ 218 struct xfs_bmap_intent *bmap; 219 220 bmap = container_of(item, struct xfs_bmap_intent, bi_list); 221 kmem_free(bmap); 222} 223 224const struct xfs_defer_op_type xfs_bmap_update_defer_type = { 225 .max_items = XFS_BUI_MAX_FAST_EXTENTS, 226 .diff_items = xfs_bmap_update_diff_items, 227 .create_intent = xfs_bmap_update_create_intent, 228 .abort_intent = xfs_bmap_update_abort_intent, 229 .log_item = xfs_bmap_update_log_item, 230 .create_done = xfs_bmap_update_create_done, 231 .finish_item = xfs_bmap_update_finish_item, 232 .cancel_item = xfs_bmap_update_cancel_item, 233};