aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/xfs/libxfs/xfs_bmap.c55
-rw-r--r--fs/xfs/libxfs/xfs_rmap.c259
-rw-r--r--fs/xfs/libxfs/xfs_rmap.h24
-rw-r--r--fs/xfs/xfs_bmap_util.c1
-rw-r--r--fs/xfs/xfs_error.h4
-rw-r--r--fs/xfs/xfs_rmap_item.c57
-rw-r--r--fs/xfs/xfs_trans.h3
-rw-r--r--fs/xfs/xfs_trans_rmap.c13
8 files changed, 400 insertions, 16 deletions
diff --git a/fs/xfs/libxfs/xfs_bmap.c b/fs/xfs/libxfs/xfs_bmap.c
index c4b89218c7eb..b060bca93402 100644
--- a/fs/xfs/libxfs/xfs_bmap.c
+++ b/fs/xfs/libxfs/xfs_bmap.c
@@ -2179,6 +2179,11 @@ xfs_bmap_add_extent_delay_real(
2179 ASSERT(0); 2179 ASSERT(0);
2180 } 2180 }
2181 2181
2182 /* add reverse mapping */
2183 error = xfs_rmap_map_extent(mp, bma->dfops, bma->ip, whichfork, new);
2184 if (error)
2185 goto done;
2186
2182 /* convert to a btree if necessary */ 2187 /* convert to a btree if necessary */
2183 if (xfs_bmap_needs_btree(bma->ip, whichfork)) { 2188 if (xfs_bmap_needs_btree(bma->ip, whichfork)) {
2184 int tmp_logflags; /* partial log flag return val */ 2189 int tmp_logflags; /* partial log flag return val */
@@ -2715,6 +2720,11 @@ xfs_bmap_add_extent_unwritten_real(
2715 ASSERT(0); 2720 ASSERT(0);
2716 } 2721 }
2717 2722
2723 /* update reverse mappings */
2724 error = xfs_rmap_convert_extent(mp, dfops, ip, XFS_DATA_FORK, new);
2725 if (error)
2726 goto done;
2727
2718 /* convert to a btree if necessary */ 2728 /* convert to a btree if necessary */
2719 if (xfs_bmap_needs_btree(ip, XFS_DATA_FORK)) { 2729 if (xfs_bmap_needs_btree(ip, XFS_DATA_FORK)) {
2720 int tmp_logflags; /* partial log flag return val */ 2730 int tmp_logflags; /* partial log flag return val */
@@ -3107,6 +3117,11 @@ xfs_bmap_add_extent_hole_real(
3107 break; 3117 break;
3108 } 3118 }
3109 3119
3120 /* add reverse mapping */
3121 error = xfs_rmap_map_extent(mp, bma->dfops, bma->ip, whichfork, new);
3122 if (error)
3123 goto done;
3124
3110 /* convert to a btree if necessary */ 3125 /* convert to a btree if necessary */
3111 if (xfs_bmap_needs_btree(bma->ip, whichfork)) { 3126 if (xfs_bmap_needs_btree(bma->ip, whichfork)) {
3112 int tmp_logflags; /* partial log flag return val */ 3127 int tmp_logflags; /* partial log flag return val */
@@ -5034,6 +5049,14 @@ xfs_bmap_del_extent(
5034 ++*idx; 5049 ++*idx;
5035 break; 5050 break;
5036 } 5051 }
5052
5053 /* remove reverse mapping */
5054 if (!delay) {
5055 error = xfs_rmap_unmap_extent(mp, dfops, ip, whichfork, del);
5056 if (error)
5057 goto done;
5058 }
5059
5037 /* 5060 /*
5038 * If we need to, add to list of extents to delete. 5061 * If we need to, add to list of extents to delete.
5039 */ 5062 */
@@ -5573,7 +5596,8 @@ xfs_bmse_shift_one(
5573 struct xfs_bmbt_rec_host *gotp, 5596 struct xfs_bmbt_rec_host *gotp,
5574 struct xfs_btree_cur *cur, 5597 struct xfs_btree_cur *cur,
5575 int *logflags, 5598 int *logflags,
5576 enum shift_direction direction) 5599 enum shift_direction direction,
5600 struct xfs_defer_ops *dfops)
5577{ 5601{
5578 struct xfs_ifork *ifp; 5602 struct xfs_ifork *ifp;
5579 struct xfs_mount *mp; 5603 struct xfs_mount *mp;
@@ -5621,9 +5645,13 @@ xfs_bmse_shift_one(
5621 /* check whether to merge the extent or shift it down */ 5645 /* check whether to merge the extent or shift it down */
5622 if (xfs_bmse_can_merge(&adj_irec, &got, 5646 if (xfs_bmse_can_merge(&adj_irec, &got,
5623 offset_shift_fsb)) { 5647 offset_shift_fsb)) {
5624 return xfs_bmse_merge(ip, whichfork, offset_shift_fsb, 5648 error = xfs_bmse_merge(ip, whichfork, offset_shift_fsb,
5625 *current_ext, gotp, adj_irecp, 5649 *current_ext, gotp, adj_irecp,
5626 cur, logflags); 5650 cur, logflags);
5651 if (error)
5652 return error;
5653 adj_irec = got;
5654 goto update_rmap;
5627 } 5655 }
5628 } else { 5656 } else {
5629 startoff = got.br_startoff + offset_shift_fsb; 5657 startoff = got.br_startoff + offset_shift_fsb;
@@ -5660,9 +5688,10 @@ update_current_ext:
5660 (*current_ext)--; 5688 (*current_ext)--;
5661 xfs_bmbt_set_startoff(gotp, startoff); 5689 xfs_bmbt_set_startoff(gotp, startoff);
5662 *logflags |= XFS_ILOG_CORE; 5690 *logflags |= XFS_ILOG_CORE;
5691 adj_irec = got;
5663 if (!cur) { 5692 if (!cur) {
5664 *logflags |= XFS_ILOG_DEXT; 5693 *logflags |= XFS_ILOG_DEXT;
5665 return 0; 5694 goto update_rmap;
5666 } 5695 }
5667 5696
5668 error = xfs_bmbt_lookup_eq(cur, got.br_startoff, got.br_startblock, 5697 error = xfs_bmbt_lookup_eq(cur, got.br_startoff, got.br_startblock,
@@ -5672,8 +5701,18 @@ update_current_ext:
5672 XFS_WANT_CORRUPTED_RETURN(mp, i == 1); 5701 XFS_WANT_CORRUPTED_RETURN(mp, i == 1);
5673 5702
5674 got.br_startoff = startoff; 5703 got.br_startoff = startoff;
5675 return xfs_bmbt_update(cur, got.br_startoff, got.br_startblock, 5704 error = xfs_bmbt_update(cur, got.br_startoff, got.br_startblock,
5676 got.br_blockcount, got.br_state); 5705 got.br_blockcount, got.br_state);
5706 if (error)
5707 return error;
5708
5709update_rmap:
5710 /* update reverse mapping */
5711 error = xfs_rmap_unmap_extent(mp, dfops, ip, whichfork, &adj_irec);
5712 if (error)
5713 return error;
5714 adj_irec.br_startoff = startoff;
5715 return xfs_rmap_map_extent(mp, dfops, ip, whichfork, &adj_irec);
5677} 5716}
5678 5717
5679/* 5718/*
@@ -5801,7 +5840,7 @@ xfs_bmap_shift_extents(
5801 while (nexts++ < num_exts) { 5840 while (nexts++ < num_exts) {
5802 error = xfs_bmse_shift_one(ip, whichfork, offset_shift_fsb, 5841 error = xfs_bmse_shift_one(ip, whichfork, offset_shift_fsb,
5803 &current_ext, gotp, cur, &logflags, 5842 &current_ext, gotp, cur, &logflags,
5804 direction); 5843 direction, dfops);
5805 if (error) 5844 if (error)
5806 goto del_cursor; 5845 goto del_cursor;
5807 /* 5846 /*
diff --git a/fs/xfs/libxfs/xfs_rmap.c b/fs/xfs/libxfs/xfs_rmap.c
index e8ce97fd0608..73d05407d663 100644
--- a/fs/xfs/libxfs/xfs_rmap.c
+++ b/fs/xfs/libxfs/xfs_rmap.c
@@ -36,6 +36,8 @@
36#include "xfs_trace.h" 36#include "xfs_trace.h"
37#include "xfs_error.h" 37#include "xfs_error.h"
38#include "xfs_extent_busy.h" 38#include "xfs_extent_busy.h"
39#include "xfs_bmap.h"
40#include "xfs_inode.h"
39 41
40/* 42/*
41 * Lookup the first record less than or equal to [bno, len, owner, offset] 43 * Lookup the first record less than or equal to [bno, len, owner, offset]
@@ -1138,3 +1140,260 @@ xfs_rmap_query_range(
1138 return xfs_btree_query_range(cur, &low_brec, &high_brec, 1140 return xfs_btree_query_range(cur, &low_brec, &high_brec,
1139 xfs_rmap_query_range_helper, &query); 1141 xfs_rmap_query_range_helper, &query);
1140} 1142}
1143
1144/* Clean up after calling xfs_rmap_finish_one. */
1145void
1146xfs_rmap_finish_one_cleanup(
1147 struct xfs_trans *tp,
1148 struct xfs_btree_cur *rcur,
1149 int error)
1150{
1151 struct xfs_buf *agbp;
1152
1153 if (rcur == NULL)
1154 return;
1155 agbp = rcur->bc_private.a.agbp;
1156 xfs_btree_del_cursor(rcur, error ? XFS_BTREE_ERROR : XFS_BTREE_NOERROR);
1157 if (error)
1158 xfs_trans_brelse(tp, agbp);
1159}
1160
1161/*
1162 * Process one of the deferred rmap operations. We pass back the
1163 * btree cursor to maintain our lock on the rmapbt between calls.
1164 * This saves time and eliminates a buffer deadlock between the
1165 * superblock and the AGF because we'll always grab them in the same
1166 * order.
1167 */
1168int
1169xfs_rmap_finish_one(
1170 struct xfs_trans *tp,
1171 enum xfs_rmap_intent_type type,
1172 __uint64_t owner,
1173 int whichfork,
1174 xfs_fileoff_t startoff,
1175 xfs_fsblock_t startblock,
1176 xfs_filblks_t blockcount,
1177 xfs_exntst_t state,
1178 struct xfs_btree_cur **pcur)
1179{
1180 struct xfs_mount *mp = tp->t_mountp;
1181 struct xfs_btree_cur *rcur;
1182 struct xfs_buf *agbp = NULL;
1183 int error = 0;
1184 xfs_agnumber_t agno;
1185 struct xfs_owner_info oinfo;
1186 xfs_agblock_t bno;
1187 bool unwritten;
1188
1189 agno = XFS_FSB_TO_AGNO(mp, startblock);
1190 ASSERT(agno != NULLAGNUMBER);
1191 bno = XFS_FSB_TO_AGBNO(mp, startblock);
1192
1193 trace_xfs_rmap_deferred(mp, agno, type, bno, owner, whichfork,
1194 startoff, blockcount, state);
1195
1196 if (XFS_TEST_ERROR(false, mp,
1197 XFS_ERRTAG_RMAP_FINISH_ONE,
1198 XFS_RANDOM_RMAP_FINISH_ONE))
1199 return -EIO;
1200
1201 /*
1202 * If we haven't gotten a cursor or the cursor AG doesn't match
1203 * the startblock, get one now.
1204 */
1205 rcur = *pcur;
1206 if (rcur != NULL && rcur->bc_private.a.agno != agno) {
1207 xfs_rmap_finish_one_cleanup(tp, rcur, 0);
1208 rcur = NULL;
1209 *pcur = NULL;
1210 }
1211 if (rcur == NULL) {
1212 /*
1213 * Refresh the freelist before we start changing the
1214 * rmapbt, because a shape change could cause us to
1215 * allocate blocks.
1216 */
1217 error = xfs_free_extent_fix_freelist(tp, agno, &agbp);
1218 if (error)
1219 return error;
1220 if (!agbp)
1221 return -EFSCORRUPTED;
1222
1223 rcur = xfs_rmapbt_init_cursor(mp, tp, agbp, agno);
1224 if (!rcur) {
1225 error = -ENOMEM;
1226 goto out_cur;
1227 }
1228 }
1229 *pcur = rcur;
1230
1231 xfs_rmap_ino_owner(&oinfo, owner, whichfork, startoff);
1232 unwritten = state == XFS_EXT_UNWRITTEN;
1233 bno = XFS_FSB_TO_AGBNO(rcur->bc_mp, startblock);
1234
1235 switch (type) {
1236 case XFS_RMAP_ALLOC:
1237 case XFS_RMAP_MAP:
1238 error = xfs_rmap_map(rcur, bno, blockcount, unwritten, &oinfo);
1239 break;
1240 case XFS_RMAP_FREE:
1241 case XFS_RMAP_UNMAP:
1242 error = xfs_rmap_unmap(rcur, bno, blockcount, unwritten,
1243 &oinfo);
1244 break;
1245 case XFS_RMAP_CONVERT:
1246 error = xfs_rmap_convert(rcur, bno, blockcount, !unwritten,
1247 &oinfo);
1248 break;
1249 default:
1250 ASSERT(0);
1251 error = -EFSCORRUPTED;
1252 }
1253 return error;
1254
1255out_cur:
1256 xfs_trans_brelse(tp, agbp);
1257
1258 return error;
1259}
1260
1261/*
1262 * Don't defer an rmap if we aren't an rmap filesystem.
1263 */
1264static bool
1265xfs_rmap_update_is_needed(
1266 struct xfs_mount *mp)
1267{
1268 return xfs_sb_version_hasrmapbt(&mp->m_sb);
1269}
1270
1271/*
1272 * Record a rmap intent; the list is kept sorted first by AG and then by
1273 * increasing age.
1274 */
1275static int
1276__xfs_rmap_add(
1277 struct xfs_mount *mp,
1278 struct xfs_defer_ops *dfops,
1279 enum xfs_rmap_intent_type type,
1280 __uint64_t owner,
1281 int whichfork,
1282 struct xfs_bmbt_irec *bmap)
1283{
1284 struct xfs_rmap_intent *ri;
1285
1286 trace_xfs_rmap_defer(mp, XFS_FSB_TO_AGNO(mp, bmap->br_startblock),
1287 type,
1288 XFS_FSB_TO_AGBNO(mp, bmap->br_startblock),
1289 owner, whichfork,
1290 bmap->br_startoff,
1291 bmap->br_blockcount,
1292 bmap->br_state);
1293
1294 ri = kmem_alloc(sizeof(struct xfs_rmap_intent), KM_SLEEP | KM_NOFS);
1295 INIT_LIST_HEAD(&ri->ri_list);
1296 ri->ri_type = type;
1297 ri->ri_owner = owner;
1298 ri->ri_whichfork = whichfork;
1299 ri->ri_bmap = *bmap;
1300
1301 xfs_defer_add(dfops, XFS_DEFER_OPS_TYPE_RMAP, &ri->ri_list);
1302 return 0;
1303}
1304
1305/* Map an extent into a file. */
1306int
1307xfs_rmap_map_extent(
1308 struct xfs_mount *mp,
1309 struct xfs_defer_ops *dfops,
1310 struct xfs_inode *ip,
1311 int whichfork,
1312 struct xfs_bmbt_irec *PREV)
1313{
1314 if (!xfs_rmap_update_is_needed(mp))
1315 return 0;
1316
1317 return __xfs_rmap_add(mp, dfops, XFS_RMAP_MAP, ip->i_ino,
1318 whichfork, PREV);
1319}
1320
1321/* Unmap an extent out of a file. */
1322int
1323xfs_rmap_unmap_extent(
1324 struct xfs_mount *mp,
1325 struct xfs_defer_ops *dfops,
1326 struct xfs_inode *ip,
1327 int whichfork,
1328 struct xfs_bmbt_irec *PREV)
1329{
1330 if (!xfs_rmap_update_is_needed(mp))
1331 return 0;
1332
1333 return __xfs_rmap_add(mp, dfops, XFS_RMAP_UNMAP, ip->i_ino,
1334 whichfork, PREV);
1335}
1336
1337/* Convert a data fork extent from unwritten to real or vice versa. */
1338int
1339xfs_rmap_convert_extent(
1340 struct xfs_mount *mp,
1341 struct xfs_defer_ops *dfops,
1342 struct xfs_inode *ip,
1343 int whichfork,
1344 struct xfs_bmbt_irec *PREV)
1345{
1346 if (!xfs_rmap_update_is_needed(mp))
1347 return 0;
1348
1349 return __xfs_rmap_add(mp, dfops, XFS_RMAP_CONVERT, ip->i_ino,
1350 whichfork, PREV);
1351}
1352
1353/* Schedule the creation of an rmap for non-file data. */
1354int
1355xfs_rmap_alloc_extent(
1356 struct xfs_mount *mp,
1357 struct xfs_defer_ops *dfops,
1358 xfs_agnumber_t agno,
1359 xfs_agblock_t bno,
1360 xfs_extlen_t len,
1361 __uint64_t owner)
1362{
1363 struct xfs_bmbt_irec bmap;
1364
1365 if (!xfs_rmap_update_is_needed(mp))
1366 return 0;
1367
1368 bmap.br_startblock = XFS_AGB_TO_FSB(mp, agno, bno);
1369 bmap.br_blockcount = len;
1370 bmap.br_startoff = 0;
1371 bmap.br_state = XFS_EXT_NORM;
1372
1373 return __xfs_rmap_add(mp, dfops, XFS_RMAP_ALLOC, owner,
1374 XFS_DATA_FORK, &bmap);
1375}
1376
1377/* Schedule the deletion of an rmap for non-file data. */
1378int
1379xfs_rmap_free_extent(
1380 struct xfs_mount *mp,
1381 struct xfs_defer_ops *dfops,
1382 xfs_agnumber_t agno,
1383 xfs_agblock_t bno,
1384 xfs_extlen_t len,
1385 __uint64_t owner)
1386{
1387 struct xfs_bmbt_irec bmap;
1388
1389 if (!xfs_rmap_update_is_needed(mp))
1390 return 0;
1391
1392 bmap.br_startblock = XFS_AGB_TO_FSB(mp, agno, bno);
1393 bmap.br_blockcount = len;
1394 bmap.br_startoff = 0;
1395 bmap.br_state = XFS_EXT_NORM;
1396
1397 return __xfs_rmap_add(mp, dfops, XFS_RMAP_FREE, owner,
1398 XFS_DATA_FORK, &bmap);
1399}
diff --git a/fs/xfs/libxfs/xfs_rmap.h b/fs/xfs/libxfs/xfs_rmap.h
index c4b1133e2ff9..71cf99a4acba 100644
--- a/fs/xfs/libxfs/xfs_rmap.h
+++ b/fs/xfs/libxfs/xfs_rmap.h
@@ -182,4 +182,28 @@ struct xfs_rmap_intent {
182 struct xfs_bmbt_irec ri_bmap; 182 struct xfs_bmbt_irec ri_bmap;
183}; 183};
184 184
185/* functions for updating the rmapbt based on bmbt map/unmap operations */
186int xfs_rmap_map_extent(struct xfs_mount *mp, struct xfs_defer_ops *dfops,
187 struct xfs_inode *ip, int whichfork,
188 struct xfs_bmbt_irec *imap);
189int xfs_rmap_unmap_extent(struct xfs_mount *mp, struct xfs_defer_ops *dfops,
190 struct xfs_inode *ip, int whichfork,
191 struct xfs_bmbt_irec *imap);
192int xfs_rmap_convert_extent(struct xfs_mount *mp, struct xfs_defer_ops *dfops,
193 struct xfs_inode *ip, int whichfork,
194 struct xfs_bmbt_irec *imap);
195int xfs_rmap_alloc_extent(struct xfs_mount *mp, struct xfs_defer_ops *dfops,
196 xfs_agnumber_t agno, xfs_agblock_t bno, xfs_extlen_t len,
197 __uint64_t owner);
198int xfs_rmap_free_extent(struct xfs_mount *mp, struct xfs_defer_ops *dfops,
199 xfs_agnumber_t agno, xfs_agblock_t bno, xfs_extlen_t len,
200 __uint64_t owner);
201
202void xfs_rmap_finish_one_cleanup(struct xfs_trans *tp,
203 struct xfs_btree_cur *rcur, int error);
204int xfs_rmap_finish_one(struct xfs_trans *tp, enum xfs_rmap_intent_type type,
205 __uint64_t owner, int whichfork, xfs_fileoff_t startoff,
206 xfs_fsblock_t startblock, xfs_filblks_t blockcount,
207 xfs_exntst_t state, struct xfs_btree_cur **pcur);
208
185#endif /* __XFS_RMAP_H__ */ 209#endif /* __XFS_RMAP_H__ */
diff --git a/fs/xfs/xfs_bmap_util.c b/fs/xfs/xfs_bmap_util.c
index 3bbe46bdbc6e..a819d7baa346 100644
--- a/fs/xfs/xfs_bmap_util.c
+++ b/fs/xfs/xfs_bmap_util.c
@@ -41,6 +41,7 @@
41#include "xfs_trace.h" 41#include "xfs_trace.h"
42#include "xfs_icache.h" 42#include "xfs_icache.h"
43#include "xfs_log.h" 43#include "xfs_log.h"
44#include "xfs_rmap_btree.h"
44 45
45/* Kernel only BMAP related definitions and functions */ 46/* Kernel only BMAP related definitions and functions */
46 47
diff --git a/fs/xfs/xfs_error.h b/fs/xfs/xfs_error.h
index da6f951435c9..3d224702fbc0 100644
--- a/fs/xfs/xfs_error.h
+++ b/fs/xfs/xfs_error.h
@@ -91,7 +91,8 @@ extern void xfs_verifier_error(struct xfs_buf *bp);
91#define XFS_ERRTAG_DIOWRITE_IOERR 20 91#define XFS_ERRTAG_DIOWRITE_IOERR 20
92#define XFS_ERRTAG_BMAPIFORMAT 21 92#define XFS_ERRTAG_BMAPIFORMAT 21
93#define XFS_ERRTAG_FREE_EXTENT 22 93#define XFS_ERRTAG_FREE_EXTENT 22
94#define XFS_ERRTAG_MAX 23 94#define XFS_ERRTAG_RMAP_FINISH_ONE 23
95#define XFS_ERRTAG_MAX 24
95 96
96/* 97/*
97 * Random factors for above tags, 1 means always, 2 means 1/2 time, etc. 98 * Random factors for above tags, 1 means always, 2 means 1/2 time, etc.
@@ -119,6 +120,7 @@ extern void xfs_verifier_error(struct xfs_buf *bp);
119#define XFS_RANDOM_DIOWRITE_IOERR (XFS_RANDOM_DEFAULT/10) 120#define XFS_RANDOM_DIOWRITE_IOERR (XFS_RANDOM_DEFAULT/10)
120#define XFS_RANDOM_BMAPIFORMAT XFS_RANDOM_DEFAULT 121#define XFS_RANDOM_BMAPIFORMAT XFS_RANDOM_DEFAULT
121#define XFS_RANDOM_FREE_EXTENT 1 122#define XFS_RANDOM_FREE_EXTENT 1
123#define XFS_RANDOM_RMAP_FINISH_ONE 1
122 124
123#ifdef DEBUG 125#ifdef DEBUG
124extern int xfs_error_test_active; 126extern int xfs_error_test_active;
diff --git a/fs/xfs/xfs_rmap_item.c b/fs/xfs/xfs_rmap_item.c
index fecd1e4d688d..6d6cc3b8d44f 100644
--- a/fs/xfs/xfs_rmap_item.c
+++ b/fs/xfs/xfs_rmap_item.c
@@ -24,11 +24,13 @@
24#include "xfs_trans_resv.h" 24#include "xfs_trans_resv.h"
25#include "xfs_bit.h" 25#include "xfs_bit.h"
26#include "xfs_mount.h" 26#include "xfs_mount.h"
27#include "xfs_defer.h"
27#include "xfs_trans.h" 28#include "xfs_trans.h"
28#include "xfs_trans_priv.h" 29#include "xfs_trans_priv.h"
29#include "xfs_buf_item.h" 30#include "xfs_buf_item.h"
30#include "xfs_rmap_item.h" 31#include "xfs_rmap_item.h"
31#include "xfs_log.h" 32#include "xfs_log.h"
33#include "xfs_rmap.h"
32 34
33 35
34kmem_zone_t *xfs_rui_zone; 36kmem_zone_t *xfs_rui_zone;
@@ -473,6 +475,12 @@ xfs_rui_recover(
473 struct xfs_map_extent *rmap; 475 struct xfs_map_extent *rmap;
474 xfs_fsblock_t startblock_fsb; 476 xfs_fsblock_t startblock_fsb;
475 bool op_ok; 477 bool op_ok;
478 struct xfs_rud_log_item *rudp;
479 enum xfs_rmap_intent_type type;
480 int whichfork;
481 xfs_exntst_t state;
482 struct xfs_trans *tp;
483 struct xfs_btree_cur *rcur = NULL;
476 484
477 ASSERT(!test_bit(XFS_RUI_RECOVERED, &ruip->rui_flags)); 485 ASSERT(!test_bit(XFS_RUI_RECOVERED, &ruip->rui_flags));
478 486
@@ -512,8 +520,53 @@ xfs_rui_recover(
512 } 520 }
513 } 521 }
514 522
515 /* XXX: do nothing for now */ 523 error = xfs_trans_alloc(mp, &M_RES(mp)->tr_itruncate, 0, 0, 0, &tp);
524 if (error)
525 return error;
526 rudp = xfs_trans_get_rud(tp, ruip, ruip->rui_format.rui_nextents);
527
528 for (i = 0; i < ruip->rui_format.rui_nextents; i++) {
529 rmap = &(ruip->rui_format.rui_extents[i]);
530 state = (rmap->me_flags & XFS_RMAP_EXTENT_UNWRITTEN) ?
531 XFS_EXT_UNWRITTEN : XFS_EXT_NORM;
532 whichfork = (rmap->me_flags & XFS_RMAP_EXTENT_ATTR_FORK) ?
533 XFS_ATTR_FORK : XFS_DATA_FORK;
534 switch (rmap->me_flags & XFS_RMAP_EXTENT_TYPE_MASK) {
535 case XFS_RMAP_EXTENT_MAP:
536 type = XFS_RMAP_MAP;
537 break;
538 case XFS_RMAP_EXTENT_UNMAP:
539 type = XFS_RMAP_UNMAP;
540 break;
541 case XFS_RMAP_EXTENT_CONVERT:
542 type = XFS_RMAP_CONVERT;
543 break;
544 case XFS_RMAP_EXTENT_ALLOC:
545 type = XFS_RMAP_ALLOC;
546 break;
547 case XFS_RMAP_EXTENT_FREE:
548 type = XFS_RMAP_FREE;
549 break;
550 default:
551 error = -EFSCORRUPTED;
552 goto abort_error;
553 }
554 error = xfs_trans_log_finish_rmap_update(tp, rudp, type,
555 rmap->me_owner, whichfork,
556 rmap->me_startoff, rmap->me_startblock,
557 rmap->me_len, state, &rcur);
558 if (error)
559 goto abort_error;
560
561 }
562
563 xfs_rmap_finish_one_cleanup(tp, rcur, error);
516 set_bit(XFS_RUI_RECOVERED, &ruip->rui_flags); 564 set_bit(XFS_RUI_RECOVERED, &ruip->rui_flags);
517 xfs_rui_release(ruip); 565 error = xfs_trans_commit(tp);
566 return error;
567
568abort_error:
569 xfs_rmap_finish_one_cleanup(tp, rcur, error);
570 xfs_trans_cancel(tp);
518 return error; 571 return error;
519} 572}
diff --git a/fs/xfs/xfs_trans.h b/fs/xfs/xfs_trans.h
index 07f4550825f6..bb4b84f9347e 100644
--- a/fs/xfs/xfs_trans.h
+++ b/fs/xfs/xfs_trans.h
@@ -35,6 +35,7 @@ struct xfs_dquot_acct;
35struct xfs_busy_extent; 35struct xfs_busy_extent;
36struct xfs_rud_log_item; 36struct xfs_rud_log_item;
37struct xfs_rui_log_item; 37struct xfs_rui_log_item;
38struct xfs_btree_cur;
38 39
39typedef struct xfs_log_item { 40typedef struct xfs_log_item {
40 struct list_head li_ail; /* AIL pointers */ 41 struct list_head li_ail; /* AIL pointers */
@@ -245,6 +246,6 @@ int xfs_trans_log_finish_rmap_update(struct xfs_trans *tp,
245 struct xfs_rud_log_item *rudp, enum xfs_rmap_intent_type type, 246 struct xfs_rud_log_item *rudp, enum xfs_rmap_intent_type type,
246 __uint64_t owner, int whichfork, xfs_fileoff_t startoff, 247 __uint64_t owner, int whichfork, xfs_fileoff_t startoff,
247 xfs_fsblock_t startblock, xfs_filblks_t blockcount, 248 xfs_fsblock_t startblock, xfs_filblks_t blockcount,
248 xfs_exntst_t state); 249 xfs_exntst_t state, struct xfs_btree_cur **pcur);
249 250
250#endif /* __XFS_TRANS_H__ */ 251#endif /* __XFS_TRANS_H__ */
diff --git a/fs/xfs/xfs_trans_rmap.c b/fs/xfs/xfs_trans_rmap.c
index baab99077f77..83414764e1ab 100644
--- a/fs/xfs/xfs_trans_rmap.c
+++ b/fs/xfs/xfs_trans_rmap.c
@@ -171,14 +171,15 @@ xfs_trans_log_finish_rmap_update(
171 xfs_fileoff_t startoff, 171 xfs_fileoff_t startoff,
172 xfs_fsblock_t startblock, 172 xfs_fsblock_t startblock,
173 xfs_filblks_t blockcount, 173 xfs_filblks_t blockcount,
174 xfs_exntst_t state) 174 xfs_exntst_t state,
175 struct xfs_btree_cur **pcur)
175{ 176{
176 uint next_extent; 177 uint next_extent;
177 struct xfs_map_extent *rmap; 178 struct xfs_map_extent *rmap;
178 int error; 179 int error;
179 180
180 /* XXX: actually finish the rmap update here */ 181 error = xfs_rmap_finish_one(tp, type, owner, whichfork, startoff,
181 error = -EFSCORRUPTED; 182 startblock, blockcount, state, pcur);
182 183
183 /* 184 /*
184 * Mark the transaction dirty, even on error. This ensures the 185 * Mark the transaction dirty, even on error. This ensures the
@@ -276,7 +277,8 @@ xfs_rmap_update_finish_item(
276 rmap->ri_bmap.br_startoff, 277 rmap->ri_bmap.br_startoff,
277 rmap->ri_bmap.br_startblock, 278 rmap->ri_bmap.br_startblock,
278 rmap->ri_bmap.br_blockcount, 279 rmap->ri_bmap.br_blockcount,
279 rmap->ri_bmap.br_state); 280 rmap->ri_bmap.br_state,
281 (struct xfs_btree_cur **)state);
280 kmem_free(rmap); 282 kmem_free(rmap);
281 return error; 283 return error;
282} 284}
@@ -288,6 +290,9 @@ xfs_rmap_update_finish_cleanup(
288 void *state, 290 void *state,
289 int error) 291 int error)
290{ 292{
293 struct xfs_btree_cur *rcur = state;
294
295 xfs_rmap_finish_one_cleanup(tp, rcur, error);
291} 296}
292 297
293/* Abort all pending RUIs. */ 298/* Abort all pending RUIs. */