Commit 5880f2d7 authored by Darrick J. Wong's avatar Darrick J. Wong Committed by Dave Chinner

xfs: create rmap update intent log items

Create rmap update intent/done log items to record redo information in
the log.  Because we need to roll transactions between updating the
bmbt mapping and updating the reverse mapping, we also have to track
the status of the metadata updates that will be recorded in the
post-roll transactions, just in case we crash before committing the
final transaction.  This mechanism enables log recovery to finish what
was already started.
Signed-off-by: default avatarDarrick J. Wong <darrick.wong@oracle.com>
Reviewed-by: default avatarBrian Foster <bfoster@redhat.com>
Signed-off-by: default avatarDave Chinner <david@fromorbit.com>
parent abf09233
......@@ -103,6 +103,7 @@ xfs-y += xfs_log.o \
xfs_extfree_item.o \
xfs_icreate_item.o \
xfs_inode_item.o \
xfs_rmap_item.o \
xfs_log_recover.o \
xfs_trans_ail.o \
xfs_trans_buf.o \
......
......@@ -110,7 +110,9 @@ static inline uint xlog_get_cycle(char *ptr)
#define XLOG_REG_TYPE_COMMIT 18
#define XLOG_REG_TYPE_TRANSHDR 19
#define XLOG_REG_TYPE_ICREATE 20
#define XLOG_REG_TYPE_MAX 20
#define XLOG_REG_TYPE_RUI_FORMAT 21
#define XLOG_REG_TYPE_RUD_FORMAT 22
#define XLOG_REG_TYPE_MAX 22
/*
* Flags to log operation header
......@@ -227,6 +229,8 @@ typedef struct xfs_trans_header {
#define XFS_LI_DQUOT 0x123d
#define XFS_LI_QUOTAOFF 0x123e
#define XFS_LI_ICREATE 0x123f
#define XFS_LI_RUI 0x1240 /* rmap update intent */
#define XFS_LI_RUD 0x1241
#define XFS_LI_TYPE_DESC \
{ XFS_LI_EFI, "XFS_LI_EFI" }, \
......@@ -236,7 +240,9 @@ typedef struct xfs_trans_header {
{ XFS_LI_BUF, "XFS_LI_BUF" }, \
{ XFS_LI_DQUOT, "XFS_LI_DQUOT" }, \
{ XFS_LI_QUOTAOFF, "XFS_LI_QUOTAOFF" }, \
{ XFS_LI_ICREATE, "XFS_LI_ICREATE" }
{ XFS_LI_ICREATE, "XFS_LI_ICREATE" }, \
{ XFS_LI_RUI, "XFS_LI_RUI" }, \
{ XFS_LI_RUD, "XFS_LI_RUD" }
/*
* Inode Log Item Format definitions.
......@@ -603,6 +609,60 @@ typedef struct xfs_efd_log_format_64 {
xfs_extent_64_t efd_extents[1]; /* array of extents freed */
} xfs_efd_log_format_64_t;
/*
* RUI/RUD (reverse mapping) log format definitions
*/
struct xfs_map_extent {
__uint64_t me_owner;
__uint64_t me_startblock;
__uint64_t me_startoff;
__uint32_t me_len;
__uint32_t me_flags;
};
/* rmap me_flags: upper bits are flags, lower byte is type code */
#define XFS_RMAP_EXTENT_MAP 1
#define XFS_RMAP_EXTENT_UNMAP 3
#define XFS_RMAP_EXTENT_CONVERT 5
#define XFS_RMAP_EXTENT_ALLOC 7
#define XFS_RMAP_EXTENT_FREE 8
#define XFS_RMAP_EXTENT_TYPE_MASK 0xFF
#define XFS_RMAP_EXTENT_ATTR_FORK (1U << 31)
#define XFS_RMAP_EXTENT_BMBT_BLOCK (1U << 30)
#define XFS_RMAP_EXTENT_UNWRITTEN (1U << 29)
#define XFS_RMAP_EXTENT_FLAGS (XFS_RMAP_EXTENT_TYPE_MASK | \
XFS_RMAP_EXTENT_ATTR_FORK | \
XFS_RMAP_EXTENT_BMBT_BLOCK | \
XFS_RMAP_EXTENT_UNWRITTEN)
/*
* This is the structure used to lay out an rui log item in the
* log. The rui_extents field is a variable size array whose
* size is given by rui_nextents.
*/
struct xfs_rui_log_format {
__uint16_t rui_type; /* rui log item type */
__uint16_t rui_size; /* size of this item */
__uint32_t rui_nextents; /* # extents to free */
__uint64_t rui_id; /* rui identifier */
struct xfs_map_extent rui_extents[1]; /* array of extents to rmap */
};
/*
* This is the structure used to lay out an rud log item in the
* log. The rud_extents array is a variable size array whose
* size is given by rud_nextents;
*/
struct xfs_rud_log_format {
__uint16_t rud_type; /* rud log item type */
__uint16_t rud_size; /* size of this item */
__uint32_t rud_nextents; /* # of extents freed */
__uint64_t rud_rui_id; /* id of corresponding rui */
struct xfs_map_extent rud_extents[1]; /* array of extents rmapped */
};
/*
* Dquot Log format definitions.
*
......
......@@ -163,4 +163,23 @@ int xfs_rmap_query_range(struct xfs_btree_cur *cur,
struct xfs_rmap_irec *low_rec, struct xfs_rmap_irec *high_rec,
xfs_rmap_query_range_fn fn, void *priv);
enum xfs_rmap_intent_type {
XFS_RMAP_MAP,
XFS_RMAP_MAP_SHARED,
XFS_RMAP_UNMAP,
XFS_RMAP_UNMAP_SHARED,
XFS_RMAP_CONVERT,
XFS_RMAP_CONVERT_SHARED,
XFS_RMAP_ALLOC,
XFS_RMAP_FREE,
};
struct xfs_rmap_intent {
struct list_head ri_list;
enum xfs_rmap_intent_type ri_type;
__uint64_t ri_owner;
int ri_whichfork;
struct xfs_bmbt_irec ri_bmap;
};
#endif /* __XFS_RMAP_H__ */
This diff is collapsed.
/*
* Copyright (C) 2016 Oracle. All Rights Reserved.
*
* Author: Darrick J. Wong <darrick.wong@oracle.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it would be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef __XFS_RMAP_ITEM_H__
#define __XFS_RMAP_ITEM_H__
/*
* There are (currently) three pairs of rmap btree redo item types: map, unmap,
* and convert. The common abbreviations for these are RUI (rmap update
* intent) and RUD (rmap update done). The redo item type is encoded in the
* flags field of each xfs_map_extent.
*
* *I items should be recorded in the *first* of a series of rolled
* transactions, and the *D items should be recorded in the same transaction
* that records the associated rmapbt updates. Typically, the first
* transaction will record a bmbt update, followed by some number of
* transactions containing rmapbt updates, and finally transactions with any
* bnobt/cntbt updates.
*
* Should the system crash after the commit of the first transaction but
* before the commit of the final transaction in a series, log recovery will
* use the redo information recorded by the intent items to replay the
* (rmapbt/bnobt/cntbt) metadata updates in the non-first transaction.
*/
/* kernel only RUI/RUD definitions */
struct xfs_mount;
struct kmem_zone;
/*
* Max number of extents in fast allocation path.
*/
#define XFS_RUI_MAX_FAST_EXTENTS 16
/*
* Define RUI flag bits. Manipulated by set/clear/test_bit operators.
*/
#define XFS_RUI_RECOVERED 1
/*
* This is the "rmap update intent" log item. It is used to log the fact that
* some reverse mappings need to change. It is used in conjunction with the
* "rmap update done" log item described below.
*
* These log items follow the same rules as struct xfs_efi_log_item; see the
* comments about that structure (in xfs_extfree_item.h) for more details.
*/
struct xfs_rui_log_item {
struct xfs_log_item rui_item;
atomic_t rui_refcount;
atomic_t rui_next_extent;
unsigned long rui_flags; /* misc flags */
struct xfs_rui_log_format rui_format;
};
/*
* This is the "rmap update done" log item. It is used to log the fact that
* some rmapbt updates mentioned in an earlier rui item have been performed.
*/
struct xfs_rud_log_item {
struct xfs_log_item rud_item;
struct xfs_rui_log_item *rud_ruip;
uint rud_next_extent;
struct xfs_rud_log_format rud_format;
};
/*
* Max number of extents in fast allocation path.
*/
#define XFS_RUD_MAX_FAST_EXTENTS 16
extern struct kmem_zone *xfs_rui_zone;
extern struct kmem_zone *xfs_rud_zone;
struct xfs_rui_log_item *xfs_rui_init(struct xfs_mount *, uint);
struct xfs_rud_log_item *xfs_rud_init(struct xfs_mount *,
struct xfs_rui_log_item *, uint);
int xfs_rui_copy_format(struct xfs_log_iovec *buf,
struct xfs_rui_log_format *dst_rui_fmt);
void xfs_rui_item_free(struct xfs_rui_log_item *);
void xfs_rui_release(struct xfs_rui_log_item *);
#endif /* __XFS_RMAP_ITEM_H__ */
......@@ -46,6 +46,7 @@
#include "xfs_quota.h"
#include "xfs_sysfs.h"
#include "xfs_ondisk.h"
#include "xfs_rmap_item.h"
#include <linux/namei.h>
#include <linux/init.h>
......@@ -1765,8 +1766,26 @@ xfs_init_zones(void)
if (!xfs_icreate_zone)
goto out_destroy_ili_zone;
xfs_rud_zone = kmem_zone_init((sizeof(struct xfs_rud_log_item) +
((XFS_RUD_MAX_FAST_EXTENTS - 1) *
sizeof(struct xfs_map_extent))),
"xfs_rud_item");
if (!xfs_rud_zone)
goto out_destroy_icreate_zone;
xfs_rui_zone = kmem_zone_init((sizeof(struct xfs_rui_log_item) +
((XFS_RUI_MAX_FAST_EXTENTS - 1) *
sizeof(struct xfs_map_extent))),
"xfs_rui_item");
if (!xfs_rui_zone)
goto out_destroy_rud_zone;
return 0;
out_destroy_rud_zone:
kmem_zone_destroy(xfs_rud_zone);
out_destroy_icreate_zone:
kmem_zone_destroy(xfs_icreate_zone);
out_destroy_ili_zone:
kmem_zone_destroy(xfs_ili_zone);
out_destroy_inode_zone:
......@@ -1805,6 +1824,8 @@ xfs_destroy_zones(void)
* destroy caches.
*/
rcu_barrier();
kmem_zone_destroy(xfs_rui_zone);
kmem_zone_destroy(xfs_rud_zone);
kmem_zone_destroy(xfs_icreate_zone);
kmem_zone_destroy(xfs_ili_zone);
kmem_zone_destroy(xfs_inode_zone);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment