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

Merge tag 'xfs-delay-ready-attrs-v20.1' of...

Merge tag 'xfs-delay-ready-attrs-v20.1' of https://github.com/allisonhenderson/xfs_work into xfs-5.14-merge4

xfs: Delay Ready Attributes

Hi all,

This set is a subset of a larger series for Dealyed Attributes. Which is a
subset of a yet larger series for parent pointers. Delayed attributes allow
attribute operations (set and remove) to be logged and committed in the same
way that other delayed operations do. This allows more complex operations (like
parent pointers) to be broken up into multiple smaller transactions. To do
this, the existing attr operations must be modified to operate as a delayed
operation.  This means that they cannot roll, commit, or finish transactions.
Instead, they return -EAGAIN to allow the calling function to handle the
transaction.  In this series, we focus on only the delayed attribute portion.
We will introduce parent pointers in a later set.

The set as a whole is a bit much to digest at once, so I usually send out the
smaller sub series to reduce reviewer burn out.  But the entire extended series
is visible through the included github links.

Updates since v19: Added Darricks fix for the remote block accounting as well as
some minor nits about the default assert in xfs_attr_set_iter.  Spent quite
a bit of time testing this cycle to weed out any more unexpected bugs.  No new
test failures were observed with the addition of this set.

xfs: Fix default ASSERT in xfs_attr_set_iter
  Replaced the assert with ASSERT(0);

xfs: Add delay ready attr remove routines
  Added Darricks fix for remote block accounting

This series can be viewed on github here:
https://github.com/allisonhenderson/xfs_work/tree/delay_ready_attrs_v20

As well as the extended delayed attribute and parent pointer series:
https://github.com/allisonhenderson/xfs_work/tree/delay_ready_attrs_v20_extended

And the test cases:
https://github.com/allisonhenderson/xfs_work/tree/pptr_xfstestsv3
In order to run the test cases, you will need have the corresponding xfsprogs

changes as well.  Which can be found here:
https://github.com/allisonhenderson/xfs_work/tree/delay_ready_attrs_xfsprogs_v20
https://github.com/allisonhenderson/xfs_work/tree/delay_ready_attrs_xfsprogs_v20_extended

To run the xfs attributes tests run:
check -g attr

To run as delayed attributes run:
export MOUNT_OPTIONS="-o delattr"
check -g attr

To run parent pointer tests:
check -g parent

I've also made the corresponding updates to the user space side as well, and ported anything
they need to seat correctly.

Questions, comment and feedback appreciated!

Thanks all!
Allison

* tag 'xfs-delay-ready-attrs-v20.1' of https://github.com/allisonhenderson/xfs_work:
  xfs: Make attr name schemes consistent
  xfs: Fix default ASSERT in xfs_attr_set_iter
  xfs: Clean up xfs_attr_node_addname_clear_incomplete
  xfs: Remove xfs_attr_rmtval_set
  xfs: Add delay ready attr set routines
  xfs: Add delay ready attr remove routines
  xfs: Hoist node transaction handling
  xfs: Hoist xfs_attr_leaf_addname
  xfs: Hoist xfs_attr_node_addname
  xfs: Add helper xfs_attr_node_addname_find_attr
  xfs: Separate xfs_attr_node_addname and xfs_attr_node_addname_clear_incomplete
  xfs: Refactor xfs_attr_set_shortform
  xfs: Add xfs_attr_node_remove_name
  xfs: Reverse apply 72b97ea4
parents 68b2c8bc 816c8e39
This diff is collapsed.
This diff is collapsed.
......@@ -19,8 +19,8 @@
#include "xfs_bmap_btree.h"
#include "xfs_bmap.h"
#include "xfs_attr_sf.h"
#include "xfs_attr_remote.h"
#include "xfs_attr.h"
#include "xfs_attr_remote.h"
#include "xfs_attr_leaf.h"
#include "xfs_error.h"
#include "xfs_trace.h"
......@@ -774,7 +774,7 @@ xfs_attr_fork_remove(
* Remove an attribute from the shortform attribute list structure.
*/
int
xfs_attr_shortform_remove(
xfs_attr_sf_removename(
struct xfs_da_args *args)
{
struct xfs_attr_shortform *sf;
......
......@@ -51,7 +51,7 @@ int xfs_attr_shortform_lookup(struct xfs_da_args *args);
int xfs_attr_shortform_getvalue(struct xfs_da_args *args);
int xfs_attr_shortform_to_leaf(struct xfs_da_args *args,
struct xfs_buf **leaf_bp);
int xfs_attr_shortform_remove(struct xfs_da_args *args);
int xfs_attr_sf_removename(struct xfs_da_args *args);
int xfs_attr_sf_findname(struct xfs_da_args *args,
struct xfs_attr_sf_entry **sfep,
unsigned int *basep);
......
......@@ -439,9 +439,9 @@ xfs_attr_rmtval_get(
/*
* Find a "hole" in the attribute address space large enough for us to drop the
* new attribute's value into
* new attributes value into
*/
STATIC int
int
xfs_attr_rmt_find_hole(
struct xfs_da_args *args)
{
......@@ -468,7 +468,7 @@ xfs_attr_rmt_find_hole(
return 0;
}
STATIC int
int
xfs_attr_rmtval_set_value(
struct xfs_da_args *args)
{
......@@ -562,69 +562,66 @@ xfs_attr_rmtval_stale(
}
/*
* Write the value associated with an attribute into the out-of-line buffer
* that we have defined for it.
* Find a hole for the attr and store it in the delayed attr context. This
* initializes the context to roll through allocating an attr extent for a
* delayed attr operation
*/
int
xfs_attr_rmtval_set(
struct xfs_da_args *args)
xfs_attr_rmtval_find_space(
struct xfs_delattr_context *dac)
{
struct xfs_inode *dp = args->dp;
struct xfs_bmbt_irec map;
xfs_dablk_t lblkno;
int blkcnt;
int nmap;
int error;
struct xfs_da_args *args = dac->da_args;
struct xfs_bmbt_irec *map = &dac->map;
int error;
trace_xfs_attr_rmtval_set(args);
dac->lblkno = 0;
dac->blkcnt = 0;
args->rmtblkcnt = 0;
args->rmtblkno = 0;
memset(map, 0, sizeof(struct xfs_bmbt_irec));
error = xfs_attr_rmt_find_hole(args);
if (error)
return error;
blkcnt = args->rmtblkcnt;
lblkno = (xfs_dablk_t)args->rmtblkno;
/*
* Roll through the "value", allocating blocks on disk as required.
*/
while (blkcnt > 0) {
/*
* Allocate a single extent, up to the size of the value.
*
* Note that we have to consider this a data allocation as we
* write the remote attribute without logging the contents.
* Hence we must ensure that we aren't using blocks that are on
* the busy list so that we don't overwrite blocks which have
* recently been freed but their transactions are not yet
* committed to disk. If we overwrite the contents of a busy
* extent and then crash then the block may not contain the
* correct metadata after log recovery occurs.
*/
nmap = 1;
error = xfs_bmapi_write(args->trans, dp, (xfs_fileoff_t)lblkno,
blkcnt, XFS_BMAPI_ATTRFORK, args->total, &map,
&nmap);
if (error)
return error;
error = xfs_defer_finish(&args->trans);
if (error)
return error;
dac->blkcnt = args->rmtblkcnt;
dac->lblkno = args->rmtblkno;
ASSERT(nmap == 1);
ASSERT((map.br_startblock != DELAYSTARTBLOCK) &&
(map.br_startblock != HOLESTARTBLOCK));
lblkno += map.br_blockcount;
blkcnt -= map.br_blockcount;
return 0;
}
/*
* Start the next trans in the chain.
*/
error = xfs_trans_roll_inode(&args->trans, dp);
if (error)
return error;
}
/*
* Write one block of the value associated with an attribute into the
* out-of-line buffer that we have defined for it. This is similar to a subset
* of xfs_attr_rmtval_set, but records the current block to the delayed attr
* context, and leaves transaction handling to the caller.
*/
int
xfs_attr_rmtval_set_blk(
struct xfs_delattr_context *dac)
{
struct xfs_da_args *args = dac->da_args;
struct xfs_inode *dp = args->dp;
struct xfs_bmbt_irec *map = &dac->map;
int nmap;
int error;
nmap = 1;
error = xfs_bmapi_write(args->trans, dp, (xfs_fileoff_t)dac->lblkno,
dac->blkcnt, XFS_BMAPI_ATTRFORK, args->total,
map, &nmap);
if (error)
return error;
ASSERT(nmap == 1);
ASSERT((map->br_startblock != DELAYSTARTBLOCK) &&
(map->br_startblock != HOLESTARTBLOCK));
return xfs_attr_rmtval_set_value(args);
/* roll attribute extent map forwards */
dac->lblkno += map->br_blockcount;
dac->blkcnt -= map->br_blockcount;
return 0;
}
/*
......@@ -668,48 +665,18 @@ xfs_attr_rmtval_invalidate(
return 0;
}
/*
* Remove the value associated with an attribute by deleting the
* out-of-line buffer that it is stored on.
*/
int
xfs_attr_rmtval_remove(
struct xfs_da_args *args)
{
int error;
int retval;
trace_xfs_attr_rmtval_remove(args);
/*
* Keep de-allocating extents until the remote-value region is gone.
*/
do {
retval = __xfs_attr_rmtval_remove(args);
if (retval && retval != -EAGAIN)
return retval;
/*
* Close out trans and start the next one in the chain.
*/
error = xfs_trans_roll_inode(&args->trans, args->dp);
if (error)
return error;
} while (retval == -EAGAIN);
return 0;
}
/*
* Remove the value associated with an attribute by deleting the out-of-line
* buffer that it is stored on. Returns EAGAIN for the caller to refresh the
* transaction and re-call the function
* buffer that it is stored on. Returns -EAGAIN for the caller to refresh the
* transaction and re-call the function. Callers should keep calling this
* routine until it returns something other than -EAGAIN.
*/
int
__xfs_attr_rmtval_remove(
struct xfs_da_args *args)
struct xfs_delattr_context *dac)
{
int error, done;
struct xfs_da_args *args = dac->da_args;
int error, done;
/*
* Unmap value blocks for this attr.
......@@ -719,12 +686,20 @@ __xfs_attr_rmtval_remove(
if (error)
return error;
error = xfs_defer_finish(&args->trans);
if (error)
return error;
if (!done)
/*
* We don't need an explicit state here to pick up where we left off. We
* can figure it out using the !done return code. The actual value of
* attr->xattri_dela_state may be some value reminiscent of the calling
* function, but it's value is irrelevant with in the context of this
* function. Once we are done here, the next state is set as needed by
* the parent
*/
if (!done) {
dac->flags |= XFS_DAC_DEFER_FINISH;
return -EAGAIN;
}
return error;
args->rmtblkno = 0;
args->rmtblkcnt = 0;
return 0;
}
......@@ -9,10 +9,12 @@
int xfs_attr3_rmt_blocks(struct xfs_mount *mp, int attrlen);
int xfs_attr_rmtval_get(struct xfs_da_args *args);
int xfs_attr_rmtval_set(struct xfs_da_args *args);
int xfs_attr_rmtval_remove(struct xfs_da_args *args);
int xfs_attr_rmtval_stale(struct xfs_inode *ip, struct xfs_bmbt_irec *map,
xfs_buf_flags_t incore_flags);
int xfs_attr_rmtval_invalidate(struct xfs_da_args *args);
int __xfs_attr_rmtval_remove(struct xfs_da_args *args);
int __xfs_attr_rmtval_remove(struct xfs_delattr_context *dac);
int xfs_attr_rmt_find_hole(struct xfs_da_args *args);
int xfs_attr_rmtval_set_value(struct xfs_da_args *args);
int xfs_attr_rmtval_set_blk(struct xfs_delattr_context *dac);
int xfs_attr_rmtval_find_space(struct xfs_delattr_context *dac);
#endif /* __XFS_ATTR_REMOTE_H__ */
......@@ -15,10 +15,10 @@
#include "xfs_da_format.h"
#include "xfs_da_btree.h"
#include "xfs_inode.h"
#include "xfs_attr.h"
#include "xfs_attr_remote.h"
#include "xfs_trans.h"
#include "xfs_bmap.h"
#include "xfs_attr.h"
#include "xfs_attr_leaf.h"
#include "xfs_quota.h"
#include "xfs_dir2.h"
......
......@@ -1912,7 +1912,6 @@ DEFINE_ATTR_EVENT(xfs_attr_leaf_add);
DEFINE_ATTR_EVENT(xfs_attr_leaf_add_old);
DEFINE_ATTR_EVENT(xfs_attr_leaf_add_new);
DEFINE_ATTR_EVENT(xfs_attr_leaf_add_work);
DEFINE_ATTR_EVENT(xfs_attr_leaf_addname);
DEFINE_ATTR_EVENT(xfs_attr_leaf_create);
DEFINE_ATTR_EVENT(xfs_attr_leaf_compact);
DEFINE_ATTR_EVENT(xfs_attr_leaf_get);
......@@ -1942,7 +1941,6 @@ DEFINE_ATTR_EVENT(xfs_attr_refillstate);
DEFINE_ATTR_EVENT(xfs_attr_rmtval_get);
DEFINE_ATTR_EVENT(xfs_attr_rmtval_set);
DEFINE_ATTR_EVENT(xfs_attr_rmtval_remove);
#define DEFINE_DA_EVENT(name) \
DEFINE_EVENT(xfs_da_class, name, \
......
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