Skip to content

Commit 77d61fe

Browse files
committed
xfs: log bmap intent items
Provide a mechanism for higher levels to create BUI/BUD items, submit them to the log, and a stub function to deal with recovered BUI items. These parts will be connected to the rmapbt in a later patch. Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com> Reviewed-by: Christoph Hellwig <hch@lst.de>
1 parent 6413a01 commit 77d61fe

File tree

7 files changed

+358
-0
lines changed

7 files changed

+358
-0
lines changed

fs/xfs/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,7 @@ xfs-y += xfs_log.o \
111111
xfs_rmap_item.o \
112112
xfs_log_recover.o \
113113
xfs_trans_ail.o \
114+
xfs_trans_bmap.o \
114115
xfs_trans_buf.o \
115116
xfs_trans_extfree.o \
116117
xfs_trans_inode.o \

fs/xfs/libxfs/xfs_bmap.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,4 +207,17 @@ int xfs_bmapi_reserve_delalloc(struct xfs_inode *ip, xfs_fileoff_t aoff,
207207
xfs_filblks_t len, struct xfs_bmbt_irec *got,
208208
struct xfs_bmbt_irec *prev, xfs_extnum_t *lastx, int eof);
209209

210+
enum xfs_bmap_intent_type {
211+
XFS_BMAP_MAP = 1,
212+
XFS_BMAP_UNMAP,
213+
};
214+
215+
struct xfs_bmap_intent {
216+
struct list_head bi_list;
217+
enum xfs_bmap_intent_type bi_type;
218+
struct xfs_inode *bi_owner;
219+
int bi_whichfork;
220+
struct xfs_bmbt_irec bi_bmap;
221+
};
222+
210223
#endif /* __XFS_BMAP_H__ */

fs/xfs/xfs_bmap_item.c

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,18 @@
2222
#include "xfs_format.h"
2323
#include "xfs_log_format.h"
2424
#include "xfs_trans_resv.h"
25+
#include "xfs_bit.h"
2526
#include "xfs_mount.h"
27+
#include "xfs_defer.h"
28+
#include "xfs_inode.h"
2629
#include "xfs_trans.h"
2730
#include "xfs_trans_priv.h"
2831
#include "xfs_buf_item.h"
2932
#include "xfs_bmap_item.h"
3033
#include "xfs_log.h"
34+
#include "xfs_bmap.h"
35+
#include "xfs_icache.h"
36+
#include "xfs_trace.h"
3137

3238

3339
kmem_zone_t *xfs_bui_zone;
@@ -372,3 +378,66 @@ xfs_bud_init(
372378

373379
return budp;
374380
}
381+
382+
/*
383+
* Process a bmap update intent item that was recovered from the log.
384+
* We need to update some inode's bmbt.
385+
*/
386+
int
387+
xfs_bui_recover(
388+
struct xfs_mount *mp,
389+
struct xfs_bui_log_item *buip)
390+
{
391+
int error = 0;
392+
struct xfs_map_extent *bmap;
393+
xfs_fsblock_t startblock_fsb;
394+
xfs_fsblock_t inode_fsb;
395+
bool op_ok;
396+
397+
ASSERT(!test_bit(XFS_BUI_RECOVERED, &buip->bui_flags));
398+
399+
/* Only one mapping operation per BUI... */
400+
if (buip->bui_format.bui_nextents != XFS_BUI_MAX_FAST_EXTENTS) {
401+
set_bit(XFS_BUI_RECOVERED, &buip->bui_flags);
402+
xfs_bui_release(buip);
403+
return -EIO;
404+
}
405+
406+
/*
407+
* First check the validity of the extent described by the
408+
* BUI. If anything is bad, then toss the BUI.
409+
*/
410+
bmap = &buip->bui_format.bui_extents[0];
411+
startblock_fsb = XFS_BB_TO_FSB(mp,
412+
XFS_FSB_TO_DADDR(mp, bmap->me_startblock));
413+
inode_fsb = XFS_BB_TO_FSB(mp, XFS_FSB_TO_DADDR(mp,
414+
XFS_INO_TO_FSB(mp, bmap->me_owner)));
415+
switch (bmap->me_flags & XFS_BMAP_EXTENT_TYPE_MASK) {
416+
case XFS_BMAP_MAP:
417+
case XFS_BMAP_UNMAP:
418+
op_ok = true;
419+
break;
420+
default:
421+
op_ok = false;
422+
break;
423+
}
424+
if (!op_ok || startblock_fsb == 0 ||
425+
bmap->me_len == 0 ||
426+
inode_fsb == 0 ||
427+
startblock_fsb >= mp->m_sb.sb_dblocks ||
428+
bmap->me_len >= mp->m_sb.sb_agblocks ||
429+
inode_fsb >= mp->m_sb.sb_dblocks ||
430+
(bmap->me_flags & ~XFS_BMAP_EXTENT_FLAGS)) {
431+
/*
432+
* This will pull the BUI from the AIL and
433+
* free the memory associated with it.
434+
*/
435+
set_bit(XFS_BUI_RECOVERED, &buip->bui_flags);
436+
xfs_bui_release(buip);
437+
return -EIO;
438+
}
439+
440+
set_bit(XFS_BUI_RECOVERED, &buip->bui_flags);
441+
xfs_bui_release(buip);
442+
return error;
443+
}

fs/xfs/xfs_bmap_item.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,5 +93,6 @@ struct xfs_bud_log_item *xfs_bud_init(struct xfs_mount *,
9393
struct xfs_bui_log_item *);
9494
void xfs_bui_item_free(struct xfs_bui_log_item *);
9595
void xfs_bui_release(struct xfs_bui_log_item *);
96+
int xfs_bui_recover(struct xfs_mount *mp, struct xfs_bui_log_item *buip);
9697

9798
#endif /* __XFS_BMAP_ITEM_H__ */

fs/xfs/xfs_log_recover.c

Lines changed: 177 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
#include "xfs_rmap_item.h"
4747
#include "xfs_buf_item.h"
4848
#include "xfs_refcount_item.h"
49+
#include "xfs_bmap_item.h"
4950

5051
#define BLK_AVG(blk1, blk2) ((blk1+blk2) >> 1)
5152

@@ -1927,6 +1928,8 @@ xlog_recover_reorder_trans(
19271928
case XFS_LI_RUD:
19281929
case XFS_LI_CUI:
19291930
case XFS_LI_CUD:
1931+
case XFS_LI_BUI:
1932+
case XFS_LI_BUD:
19301933
trace_xfs_log_recover_item_reorder_tail(log,
19311934
trans, item, pass);
19321935
list_move_tail(&item->ri_list, &inode_list);
@@ -3670,6 +3673,125 @@ xlog_recover_cud_pass2(
36703673
return 0;
36713674
}
36723675

3676+
/*
3677+
* Copy an BUI format buffer from the given buf, and into the destination
3678+
* BUI format structure. The BUI/BUD items were designed not to need any
3679+
* special alignment handling.
3680+
*/
3681+
static int
3682+
xfs_bui_copy_format(
3683+
struct xfs_log_iovec *buf,
3684+
struct xfs_bui_log_format *dst_bui_fmt)
3685+
{
3686+
struct xfs_bui_log_format *src_bui_fmt;
3687+
uint len;
3688+
3689+
src_bui_fmt = buf->i_addr;
3690+
len = xfs_bui_log_format_sizeof(src_bui_fmt->bui_nextents);
3691+
3692+
if (buf->i_len == len) {
3693+
memcpy(dst_bui_fmt, src_bui_fmt, len);
3694+
return 0;
3695+
}
3696+
return -EFSCORRUPTED;
3697+
}
3698+
3699+
/*
3700+
* This routine is called to create an in-core extent bmap update
3701+
* item from the bui format structure which was logged on disk.
3702+
* It allocates an in-core bui, copies the extents from the format
3703+
* structure into it, and adds the bui to the AIL with the given
3704+
* LSN.
3705+
*/
3706+
STATIC int
3707+
xlog_recover_bui_pass2(
3708+
struct xlog *log,
3709+
struct xlog_recover_item *item,
3710+
xfs_lsn_t lsn)
3711+
{
3712+
int error;
3713+
struct xfs_mount *mp = log->l_mp;
3714+
struct xfs_bui_log_item *buip;
3715+
struct xfs_bui_log_format *bui_formatp;
3716+
3717+
bui_formatp = item->ri_buf[0].i_addr;
3718+
3719+
if (bui_formatp->bui_nextents != XFS_BUI_MAX_FAST_EXTENTS)
3720+
return -EFSCORRUPTED;
3721+
buip = xfs_bui_init(mp);
3722+
error = xfs_bui_copy_format(&item->ri_buf[0], &buip->bui_format);
3723+
if (error) {
3724+
xfs_bui_item_free(buip);
3725+
return error;
3726+
}
3727+
atomic_set(&buip->bui_next_extent, bui_formatp->bui_nextents);
3728+
3729+
spin_lock(&log->l_ailp->xa_lock);
3730+
/*
3731+
* The RUI has two references. One for the RUD and one for RUI to ensure
3732+
* it makes it into the AIL. Insert the RUI into the AIL directly and
3733+
* drop the RUI reference. Note that xfs_trans_ail_update() drops the
3734+
* AIL lock.
3735+
*/
3736+
xfs_trans_ail_update(log->l_ailp, &buip->bui_item, lsn);
3737+
xfs_bui_release(buip);
3738+
return 0;
3739+
}
3740+
3741+
3742+
/*
3743+
* This routine is called when an BUD format structure is found in a committed
3744+
* transaction in the log. Its purpose is to cancel the corresponding BUI if it
3745+
* was still in the log. To do this it searches the AIL for the BUI with an id
3746+
* equal to that in the BUD format structure. If we find it we drop the BUD
3747+
* reference, which removes the BUI from the AIL and frees it.
3748+
*/
3749+
STATIC int
3750+
xlog_recover_bud_pass2(
3751+
struct xlog *log,
3752+
struct xlog_recover_item *item)
3753+
{
3754+
struct xfs_bud_log_format *bud_formatp;
3755+
struct xfs_bui_log_item *buip = NULL;
3756+
struct xfs_log_item *lip;
3757+
__uint64_t bui_id;
3758+
struct xfs_ail_cursor cur;
3759+
struct xfs_ail *ailp = log->l_ailp;
3760+
3761+
bud_formatp = item->ri_buf[0].i_addr;
3762+
if (item->ri_buf[0].i_len != sizeof(struct xfs_bud_log_format))
3763+
return -EFSCORRUPTED;
3764+
bui_id = bud_formatp->bud_bui_id;
3765+
3766+
/*
3767+
* Search for the BUI with the id in the BUD format structure in the
3768+
* AIL.
3769+
*/
3770+
spin_lock(&ailp->xa_lock);
3771+
lip = xfs_trans_ail_cursor_first(ailp, &cur, 0);
3772+
while (lip != NULL) {
3773+
if (lip->li_type == XFS_LI_BUI) {
3774+
buip = (struct xfs_bui_log_item *)lip;
3775+
if (buip->bui_format.bui_id == bui_id) {
3776+
/*
3777+
* Drop the BUD reference to the BUI. This
3778+
* removes the BUI from the AIL and frees it.
3779+
*/
3780+
spin_unlock(&ailp->xa_lock);
3781+
xfs_bui_release(buip);
3782+
spin_lock(&ailp->xa_lock);
3783+
break;
3784+
}
3785+
}
3786+
lip = xfs_trans_ail_cursor_next(ailp, &cur);
3787+
}
3788+
3789+
xfs_trans_ail_cursor_done(&cur);
3790+
spin_unlock(&ailp->xa_lock);
3791+
3792+
return 0;
3793+
}
3794+
36733795
/*
36743796
* This routine is called when an inode create format structure is found in a
36753797
* committed transaction in the log. It's purpose is to initialise the inodes
@@ -3899,6 +4021,8 @@ xlog_recover_ra_pass2(
38994021
case XFS_LI_RUD:
39004022
case XFS_LI_CUI:
39014023
case XFS_LI_CUD:
4024+
case XFS_LI_BUI:
4025+
case XFS_LI_BUD:
39024026
default:
39034027
break;
39044028
}
@@ -3926,6 +4050,8 @@ xlog_recover_commit_pass1(
39264050
case XFS_LI_RUD:
39274051
case XFS_LI_CUI:
39284052
case XFS_LI_CUD:
4053+
case XFS_LI_BUI:
4054+
case XFS_LI_BUD:
39294055
/* nothing to do in pass 1 */
39304056
return 0;
39314057
default:
@@ -3964,6 +4090,10 @@ xlog_recover_commit_pass2(
39644090
return xlog_recover_cui_pass2(log, item, trans->r_lsn);
39654091
case XFS_LI_CUD:
39664092
return xlog_recover_cud_pass2(log, item);
4093+
case XFS_LI_BUI:
4094+
return xlog_recover_bui_pass2(log, item, trans->r_lsn);
4095+
case XFS_LI_BUD:
4096+
return xlog_recover_bud_pass2(log, item);
39674097
case XFS_LI_DQUOT:
39684098
return xlog_recover_dquot_pass2(log, buffer_list, item,
39694099
trans->r_lsn);
@@ -4591,13 +4721,54 @@ xlog_recover_cancel_cui(
45914721
spin_lock(&ailp->xa_lock);
45924722
}
45934723

4724+
/* Recover the BUI if necessary. */
4725+
STATIC int
4726+
xlog_recover_process_bui(
4727+
struct xfs_mount *mp,
4728+
struct xfs_ail *ailp,
4729+
struct xfs_log_item *lip)
4730+
{
4731+
struct xfs_bui_log_item *buip;
4732+
int error;
4733+
4734+
/*
4735+
* Skip BUIs that we've already processed.
4736+
*/
4737+
buip = container_of(lip, struct xfs_bui_log_item, bui_item);
4738+
if (test_bit(XFS_BUI_RECOVERED, &buip->bui_flags))
4739+
return 0;
4740+
4741+
spin_unlock(&ailp->xa_lock);
4742+
error = xfs_bui_recover(mp, buip);
4743+
spin_lock(&ailp->xa_lock);
4744+
4745+
return error;
4746+
}
4747+
4748+
/* Release the BUI since we're cancelling everything. */
4749+
STATIC void
4750+
xlog_recover_cancel_bui(
4751+
struct xfs_mount *mp,
4752+
struct xfs_ail *ailp,
4753+
struct xfs_log_item *lip)
4754+
{
4755+
struct xfs_bui_log_item *buip;
4756+
4757+
buip = container_of(lip, struct xfs_bui_log_item, bui_item);
4758+
4759+
spin_unlock(&ailp->xa_lock);
4760+
xfs_bui_release(buip);
4761+
spin_lock(&ailp->xa_lock);
4762+
}
4763+
45944764
/* Is this log item a deferred action intent? */
45954765
static inline bool xlog_item_is_intent(struct xfs_log_item *lip)
45964766
{
45974767
switch (lip->li_type) {
45984768
case XFS_LI_EFI:
45994769
case XFS_LI_RUI:
46004770
case XFS_LI_CUI:
4771+
case XFS_LI_BUI:
46014772
return true;
46024773
default:
46034774
return false;
@@ -4664,6 +4835,9 @@ xlog_recover_process_intents(
46644835
case XFS_LI_CUI:
46654836
error = xlog_recover_process_cui(log->l_mp, ailp, lip);
46664837
break;
4838+
case XFS_LI_BUI:
4839+
error = xlog_recover_process_bui(log->l_mp, ailp, lip);
4840+
break;
46674841
}
46684842
if (error)
46694843
goto out;
@@ -4714,6 +4888,9 @@ xlog_recover_cancel_intents(
47144888
case XFS_LI_CUI:
47154889
xlog_recover_cancel_cui(log->l_mp, ailp, lip);
47164890
break;
4891+
case XFS_LI_BUI:
4892+
xlog_recover_cancel_bui(log->l_mp, ailp, lip);
4893+
break;
47174894
}
47184895

47194896
lip = xfs_trans_ail_cursor_next(ailp, &cur);

fs/xfs/xfs_trans.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ struct xfs_btree_cur;
3939
struct xfs_cui_log_item;
4040
struct xfs_cud_log_item;
4141
struct xfs_defer_ops;
42+
struct xfs_bui_log_item;
4243

4344
typedef struct xfs_log_item {
4445
struct list_head li_ail; /* AIL pointers */
@@ -263,4 +264,16 @@ int xfs_trans_log_finish_refcount_update(struct xfs_trans *tp,
263264
xfs_extlen_t blockcount, xfs_fsblock_t *new_fsb,
264265
xfs_extlen_t *new_len, struct xfs_btree_cur **pcur);
265266

267+
/* mapping updates */
268+
enum xfs_bmap_intent_type;
269+
270+
void xfs_bmap_update_init_defer_op(void);
271+
struct xfs_bud_log_item *xfs_trans_get_bud(struct xfs_trans *tp,
272+
struct xfs_bui_log_item *buip);
273+
int xfs_trans_log_finish_bmap_update(struct xfs_trans *tp,
274+
struct xfs_bud_log_item *rudp, struct xfs_defer_ops *dfops,
275+
enum xfs_bmap_intent_type type, struct xfs_inode *ip,
276+
int whichfork, xfs_fileoff_t startoff, xfs_fsblock_t startblock,
277+
xfs_filblks_t blockcount, xfs_exntst_t state);
278+
266279
#endif /* __XFS_TRANS_H__ */

0 commit comments

Comments
 (0)