Commit baf4bcac authored by Darrick J. Wong's avatar Darrick J. Wong

xfs: create refcount update intent log items

Create refcount 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 avatarChristoph Hellwig <hch@lst.de>
parent bdf28630
......@@ -106,6 +106,7 @@ xfs-y += xfs_log.o \
xfs_extfree_item.o \
xfs_icreate_item.o \
xfs_inode_item.o \
xfs_refcount_item.o \
xfs_rmap_item.o \
xfs_log_recover.o \
xfs_trans_ail.o \
......
......@@ -112,7 +112,9 @@ static inline uint xlog_get_cycle(char *ptr)
#define XLOG_REG_TYPE_ICREATE 20
#define XLOG_REG_TYPE_RUI_FORMAT 21
#define XLOG_REG_TYPE_RUD_FORMAT 22
#define XLOG_REG_TYPE_MAX 22
#define XLOG_REG_TYPE_CUI_FORMAT 23
#define XLOG_REG_TYPE_CUD_FORMAT 24
#define XLOG_REG_TYPE_MAX 24
/*
* Flags to log operation header
......@@ -231,6 +233,8 @@ typedef struct xfs_trans_header {
#define XFS_LI_ICREATE 0x123f
#define XFS_LI_RUI 0x1240 /* rmap update intent */
#define XFS_LI_RUD 0x1241
#define XFS_LI_CUI 0x1242 /* refcount update intent */
#define XFS_LI_CUD 0x1243
#define XFS_LI_TYPE_DESC \
{ XFS_LI_EFI, "XFS_LI_EFI" }, \
......@@ -242,7 +246,9 @@ typedef struct xfs_trans_header {
{ XFS_LI_QUOTAOFF, "XFS_LI_QUOTAOFF" }, \
{ XFS_LI_ICREATE, "XFS_LI_ICREATE" }, \
{ XFS_LI_RUI, "XFS_LI_RUI" }, \
{ XFS_LI_RUD, "XFS_LI_RUD" }
{ XFS_LI_RUD, "XFS_LI_RUD" }, \
{ XFS_LI_CUI, "XFS_LI_CUI" }, \
{ XFS_LI_CUD, "XFS_LI_CUD" }
/*
* Inode Log Item Format definitions.
......@@ -670,6 +676,54 @@ struct xfs_rud_log_format {
__uint64_t rud_rui_id; /* id of corresponding rui */
};
/*
* CUI/CUD (refcount update) log format definitions
*/
struct xfs_phys_extent {
__uint64_t pe_startblock;
__uint32_t pe_len;
__uint32_t pe_flags;
};
/* refcount pe_flags: upper bits are flags, lower byte is type code */
/* Type codes are taken directly from enum xfs_refcount_intent_type. */
#define XFS_REFCOUNT_EXTENT_TYPE_MASK 0xFF
#define XFS_REFCOUNT_EXTENT_FLAGS (XFS_REFCOUNT_EXTENT_TYPE_MASK)
/*
* This is the structure used to lay out a cui log item in the
* log. The cui_extents field is a variable size array whose
* size is given by cui_nextents.
*/
struct xfs_cui_log_format {
__uint16_t cui_type; /* cui log item type */
__uint16_t cui_size; /* size of this item */
__uint32_t cui_nextents; /* # extents to free */
__uint64_t cui_id; /* cui identifier */
struct xfs_phys_extent cui_extents[]; /* array of extents */
};
static inline size_t
xfs_cui_log_format_sizeof(
unsigned int nr)
{
return sizeof(struct xfs_cui_log_format) +
nr * sizeof(struct xfs_phys_extent);
}
/*
* This is the structure used to lay out a cud log item in the
* log. The cud_extents array is a variable size array whose
* size is given by cud_nextents;
*/
struct xfs_cud_log_format {
__uint16_t cud_type; /* cud log item type */
__uint16_t cud_size; /* size of this item */
__uint32_t __pad;
__uint64_t cud_cui_id; /* id of corresponding cui */
};
/*
* Dquot Log format definitions.
*
......
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_REFCOUNT_ITEM_H__
#define __XFS_REFCOUNT_ITEM_H__
/*
* There are (currently) two pairs of refcount btree redo item types:
* increase and decrease. The log items for these are CUI (refcount
* update intent) and CUD (refcount 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 refcountbt 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 refcountbt metadata updates.
*/
/* kernel only CUI/CUD definitions */
struct xfs_mount;
struct kmem_zone;
/*
* Max number of extents in fast allocation path.
*/
#define XFS_CUI_MAX_FAST_EXTENTS 16
/*
* Define CUI flag bits. Manipulated by set/clear/test_bit operators.
*/
#define XFS_CUI_RECOVERED 1
/*
* This is the "refcount 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 "refcount 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_cui_log_item {
struct xfs_log_item cui_item;
atomic_t cui_refcount;
atomic_t cui_next_extent;
unsigned long cui_flags; /* misc flags */
struct xfs_cui_log_format cui_format;
};
static inline size_t
xfs_cui_log_item_sizeof(
unsigned int nr)
{
return offsetof(struct xfs_cui_log_item, cui_format) +
xfs_cui_log_format_sizeof(nr);
}
/*
* This is the "refcount update done" log item. It is used to log the
* fact that some refcountbt updates mentioned in an earlier cui item
* have been performed.
*/
struct xfs_cud_log_item {
struct xfs_log_item cud_item;
struct xfs_cui_log_item *cud_cuip;
struct xfs_cud_log_format cud_format;
};
extern struct kmem_zone *xfs_cui_zone;
extern struct kmem_zone *xfs_cud_zone;
struct xfs_cui_log_item *xfs_cui_init(struct xfs_mount *, uint);
struct xfs_cud_log_item *xfs_cud_init(struct xfs_mount *,
struct xfs_cui_log_item *);
void xfs_cui_item_free(struct xfs_cui_log_item *);
void xfs_cui_release(struct xfs_cui_log_item *);
#endif /* __XFS_REFCOUNT_ITEM_H__ */
......@@ -47,6 +47,7 @@
#include "xfs_sysfs.h"
#include "xfs_ondisk.h"
#include "xfs_rmap_item.h"
#include "xfs_refcount_item.h"
#include <linux/namei.h>
#include <linux/init.h>
......@@ -1788,8 +1789,23 @@ xfs_init_zones(void)
if (!xfs_rui_zone)
goto out_destroy_rud_zone;
xfs_cud_zone = kmem_zone_init(sizeof(struct xfs_cud_log_item),
"xfs_cud_item");
if (!xfs_cud_zone)
goto out_destroy_rui_zone;
xfs_cui_zone = kmem_zone_init(
xfs_cui_log_item_sizeof(XFS_CUI_MAX_FAST_EXTENTS),
"xfs_cui_item");
if (!xfs_cui_zone)
goto out_destroy_cud_zone;
return 0;
out_destroy_cud_zone:
kmem_zone_destroy(xfs_cud_zone);
out_destroy_rui_zone:
kmem_zone_destroy(xfs_rui_zone);
out_destroy_rud_zone:
kmem_zone_destroy(xfs_rud_zone);
out_destroy_icreate_zone:
......@@ -1832,6 +1848,8 @@ xfs_destroy_zones(void)
* destroy caches.
*/
rcu_barrier();
kmem_zone_destroy(xfs_cui_zone);
kmem_zone_destroy(xfs_cud_zone);
kmem_zone_destroy(xfs_rui_zone);
kmem_zone_destroy(xfs_rud_zone);
kmem_zone_destroy(xfs_icreate_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