From: Allison Collins <allison.henderson@oracle.com>
To: Brian Foster <bfoster@redhat.com>
Cc: linux-xfs@vger.kernel.org
Subject: Re: [PATCH v3 04/19] xfs: Add xfs_has_attr and subroutines
Date: Thu, 19 Sep 2019 16:51:02 -0700 [thread overview]
Message-ID: <de154abf-b2a9-af27-6f1b-e67f19860e62@oracle.com> (raw)
In-Reply-To: <20190919174744.GH35460@bfoster>
On 9/19/19 10:47 AM, Brian Foster wrote:
> On Thu, Sep 05, 2019 at 03:18:22PM -0700, Allison Collins wrote:
>> From: Allison Henderson <allison.henderson@oracle.com>
>>
>> This patch adds a new functions to check for the existence of
>> an attribute. Subroutines are also added to handle the cases
>> of leaf blocks, nodes or shortform. Common code that appears
>> in existing attr add and remove functions have been factored
>> out to help reduce the appearence of duplicated code. We will
>> need these routines later for delayed attributes since delayed
>> operations cannot return error codes.
>>
>> Signed-off-by: Allison Henderson <allison.henderson@oracle.com>
>> Signed-off-by: Allison Collins <allison.henderson@oracle.com>
>
> Extra s-o-b tag?
Oops, I thought I had caught all the old names. Will clean out :-)
>
>> ---
>> fs/xfs/libxfs/xfs_attr.c | 150 +++++++++++++++++++++++++++---------------
>> fs/xfs/libxfs/xfs_attr.h | 1 +
>> fs/xfs/libxfs/xfs_attr_leaf.c | 92 +++++++++++++++++---------
>> fs/xfs/libxfs/xfs_attr_leaf.h | 2 +
>> 4 files changed, 161 insertions(+), 84 deletions(-)
>>
>> diff --git a/fs/xfs/libxfs/xfs_attr.c b/fs/xfs/libxfs/xfs_attr.c
>> index 50e099f..a297857 100644
>> --- a/fs/xfs/libxfs/xfs_attr.c
>> +++ b/fs/xfs/libxfs/xfs_attr.c
>> @@ -46,6 +46,7 @@ STATIC int xfs_attr_shortform_addname(xfs_da_args_t *args);
>> STATIC int xfs_attr_leaf_get(xfs_da_args_t *args);
>> STATIC int xfs_attr_leaf_addname(xfs_da_args_t *args);
>> STATIC int xfs_attr_leaf_removename(xfs_da_args_t *args);
>> +STATIC int xfs_leaf_has_attr(struct xfs_da_args *args, struct xfs_buf **bp);
>>
>
> The fact that this is not named xfs_attr_leaf_*() kind of stands out
> here, particularly since the node variant uses the xfs_attr_* prefix.
> Hm? (Same goes for xfs_shortform_has_attr() I suppose..).
Sure, I can flip the prefixes around to look a little more consistent
>
>> /*
>> * Internal routines when attribute list is more than one block.
>> @@ -53,6 +54,8 @@ STATIC int xfs_attr_leaf_removename(xfs_da_args_t *args);
>> STATIC int xfs_attr_node_get(xfs_da_args_t *args);
>> STATIC int xfs_attr_node_addname(xfs_da_args_t *args);
>> STATIC int xfs_attr_node_removename(xfs_da_args_t *args);
>> +STATIC int xfs_attr_node_hasname(xfs_da_args_t *args,
>> + struct xfs_da_state **state);
>> STATIC int xfs_attr_fillstate(xfs_da_state_t *state);
>> STATIC int xfs_attr_refillstate(xfs_da_state_t *state);
>>
>> @@ -309,6 +312,32 @@ xfs_attr_set_args(
>> }
>>
>> /*
>> + * Return EEXIST if attr is found, or ENOATTR if not
>> + */
>> +int
>> +xfs_has_attr(
>> + struct xfs_da_args *args)
>> +{
>> + struct xfs_inode *dp = args->dp;
>> + struct xfs_buf *bp;
>> + int error;
>> +
>> + if (!xfs_inode_hasattr(dp)) {
>> + error = -ENOATTR;
>> + } else if (dp->i_d.di_aformat == XFS_DINODE_FMT_LOCAL) {
>> + ASSERT(dp->i_afp->if_flags & XFS_IFINLINE);
>> + error = xfs_shortform_has_attr(args, NULL, NULL);
>> + } else if (xfs_bmap_one_block(dp, XFS_ATTR_FORK)) {
>> + error = xfs_leaf_has_attr(args, &bp);
>> + xfs_trans_brelse(args->trans, bp);
>> + } else {
>> + error = xfs_attr_node_hasname(args, NULL);
>> + }
>> +
>> + return error;
>> +}
>> +
>
> FWIW, I think it's preferable to include new functions like this with
> the first user. I'm a bit curious about the use of error codes here as
> opposed to returning a boolean. I could see being able to handle
> unexpected errors as a good reason for doing that, but taking a quick
> look ahead, it appears neither caller of xfs_has_attr() does so. ;)
>
> (To be clear, I think keeping the function as is and fixing up the
> eventual callers to handle unexpected errors is probably the right thing
> to do.).
The new top level function actually doesnt get used until patch 18, but
I guess I try to keep the patch sizes small to make them easier for
people to review. Basically we use it to see if there is/isnt an
attribute present, and then return the appropriate error code right
away. IE, trying to remove an attribute that isnt there immediately
return EENOATTR rather than trying to start a delayed operation that
isnt going to be successful. The is because delayed operations are not
supposed to return error codes. If they do, they cause a shut down,
which is not correct here.
Initially I think I had it returning booleans, but it means the top
level function needs to do extra handling to translate the error codes,
and I thought it looked messy. So I decided to stick with the scheme
that the rest of the code was using.
I skipped ahead about unexpected error codes and see what you mean, so I
will add some extra handlers there.
>
>> +/*
>> * Remove the attribute specified in @args.
>> */
>> int
>> @@ -574,26 +603,17 @@ STATIC int
>> xfs_attr_leaf_addname(
>> struct xfs_da_args *args)
>> {
>> - struct xfs_inode *dp;
>> struct xfs_buf *bp;
>> int retval, error, forkoff;
>> + struct xfs_inode *dp = args->dp;
>>
>> trace_xfs_attr_leaf_addname(args);
>>
>> /*
>> - * Read the (only) block in the attribute list in.
>> - */
>> - dp = args->dp;
>> - args->blkno = 0;
>> - error = xfs_attr3_leaf_read(args->trans, args->dp, args->blkno, -1, &bp);
>> - if (error)
>> - return error;
>> -
>
> It looks like we lose this unexpected error check here (i.e. suppose we
> got -ENOMEM or -EFSCORRUPTED or something that indicates we shouldn't
> continue). FWIW, this seems to repeat throughout this patch where we've
> invoked the new helpers..
Ok, I'll add in an explicit check for (retval != -ENOATTR && retval !=
-EEXIST)
>
>> - /*
>> * Look up the given attribute in the leaf block. Figure out if
>> * the given flags produce an error or call for an atomic rename.
>> */
>> - retval = xfs_attr3_leaf_lookup_int(bp, args);
>> + retval = xfs_leaf_has_attr(args, &bp);
>> if ((args->name.type & ATTR_REPLACE) && (retval == -ENOATTR)) {
>> xfs_trans_brelse(args->trans, bp);
>> return retval;
>> @@ -745,6 +765,25 @@ xfs_attr_leaf_addname(
>> }
>>
>> /*
>> + * Return EEXIST if attr is found, or ENOATTR if not
>> + */
>> +STATIC int
>> +xfs_leaf_has_attr(
>> + struct xfs_da_args *args,
>> + struct xfs_buf **bp)
>> +{
>> + int error = 0;
>> +
>> + args->blkno = 0;
>
> This seems misplaced for a helper, but I could be missing context. Why
> not just pass zero directly and leave the args->blkno assignment to the
> caller?
I guess just I kept these two lines together since that's was how they
initially appeared before factoring them out, but it does look a bit
off. It should be ok leave the assignment to the caller. I can push it
back up.
>
>> + error = xfs_attr3_leaf_read(args->trans, args->dp,
>> + args->blkno, XFS_DABUF_MAP_NOMAPPING, bp);
>> + if (error)
>> + return error;
>> +
>> + return xfs_attr3_leaf_lookup_int(*bp, args);
>> +}
>> +
>> +/*
>> * Remove a name from the leaf attribute list structure
>> *
>> * This leaf block cannot have a "remote" value, we only call this routine
>> @@ -764,12 +803,8 @@ xfs_attr_leaf_removename(
>> * Remove the attribute.
>> */
>> dp = args->dp;
>> - args->blkno = 0;
>> - error = xfs_attr3_leaf_read(args->trans, args->dp, args->blkno, -1, &bp);
>> - if (error)
>> - return error;
>
> Lost error check.
>
>>
>> - error = xfs_attr3_leaf_lookup_int(bp, args);
>> + error = xfs_leaf_has_attr(args, &bp);
>> if (error == -ENOATTR) {
>> xfs_trans_brelse(args->trans, bp);
>> return error;
>> @@ -808,12 +843,7 @@ xfs_attr_leaf_get(xfs_da_args_t *args)
>>
>> trace_xfs_attr_leaf_get(args);
>>
>> - args->blkno = 0;
>> - error = xfs_attr3_leaf_read(args->trans, args->dp, args->blkno, -1, &bp);
>> - if (error)
>> - return error;
>> -
>
> ^ here too. Not sure if I caught them all, but you get the idea. ;)
Ok,I'll sweep through and find them :-)
>
>> - error = xfs_attr3_leaf_lookup_int(bp, args);
>> + error = xfs_leaf_has_attr(args, &bp);
>> if (error != -EEXIST) {
>> xfs_trans_brelse(args->trans, bp);
>> return error;
>> @@ -823,6 +853,43 @@ xfs_attr_leaf_get(xfs_da_args_t *args)
>> return error;
>> }
>>
>> +/*
>> + * Return EEXIST if attr is found, or ENOATTR if not
>> + * statep: If not null is set to point at the found state. Caller will
>> + * be responsible for freeing the state in this case.
>> + */
>> +STATIC int
>> +xfs_attr_node_hasname(
>> + struct xfs_da_args *args,
>> + struct xfs_da_state **statep)
>> +{
>> + struct xfs_da_state *state;
>> + struct xfs_inode *dp;
>> + int retval, error;
>> +
>> + /*
>> + * Tie a string around our finger to remind us where we are.
>> + */
>> + dp = args->dp;
>> + state = xfs_da_state_alloc();
>> + state->args = args;
>> + state->mp = dp->i_mount;
>> +
>
> No real need for the dp local variable here if it's just to reference
> ->i_mount. Also I know that comment isn't introduced by this patch, but
> any idea what it actually means? It doesn't make much sense to me at a
> glance. :P
Ok, will clean out assignment. I'm actually not sure as to the comments
origins either, I assumed it was in reference the the state? I suppose
state is used to keep track of a lot of things going on in the calling
function. But even in that context, I don't find the comment
particularly descriptive. Should I clean it out?
>
>> + /*
>> + * Search to see if name exists, and get back a pointer to it.
>> + */
>> + error = xfs_da3_node_lookup_int(state, &retval);
>> + if (error == 0)
>> + error = retval;
>> +
>> + if (statep != NULL)
>> + *statep = state;
>> + else
>> + xfs_da_state_free(state);
>> +
>> + return error;
>> +}
>> +
>> /*========================================================================
>> * External routines when attribute list size > geo->blksize
>> *========================================================================*/
>> @@ -855,17 +922,14 @@ xfs_attr_node_addname(
>> dp = args->dp;
>> mp = dp->i_mount;
>> restart:
>> - state = xfs_da_state_alloc();
>> - state->args = args;
>> - state->mp = mp;
>> -
>> /*
>> * Search to see if name already exists, and get back a pointer
>> * to where it should go.
>> */
>> - error = xfs_da3_node_lookup_int(state, &retval);
>> - if (error)
>
> Error check again.
>
>> + error = xfs_attr_node_hasname(args, &state);
>> + if (error == -EEXIST)
>> goto out;
>> +
>> blk = &state->path.blk[ state->path.active-1 ];
>> ASSERT(blk->magic == XFS_ATTR_LEAF_MAGIC);
>> if ((args->name.type & ATTR_REPLACE) && (retval == -ENOATTR)) {
>> @@ -1070,29 +1134,15 @@ xfs_attr_node_removename(
>> {
>> struct xfs_da_state *state;
>> struct xfs_da_state_blk *blk;
>> - struct xfs_inode *dp;
>> struct xfs_buf *bp;
>> int retval, error, forkoff;
>> + struct xfs_inode *dp = args->dp;
>>
>> trace_xfs_attr_node_removename(args);
>>
>> - /*
>> - * Tie a string around our finger to remind us where we are.
>> - */
>> - dp = args->dp;
>> - state = xfs_da_state_alloc();
>> - state->args = args;
>> - state->mp = dp->i_mount;
>> -
>> - /*
>> - * Search to see if name exists, and get back a pointer to it.
>> - */
>> - error = xfs_da3_node_lookup_int(state, &retval);
>> - if (error || (retval != -EEXIST)) {
>> - if (error == 0)
>> - error = retval;
>> + error = xfs_attr_node_hasname(args, &state);
>> + if (error != -EEXIST)
>> goto out;
>> - }
>>
>> /*
>> * If there is an out-of-line value, de-allocate the blocks.
>> @@ -1314,20 +1364,14 @@ xfs_attr_node_get(xfs_da_args_t *args)
>>
>> trace_xfs_attr_node_get(args);
>>
>> - state = xfs_da_state_alloc();
>> - state->args = args;
>> - state->mp = args->dp->i_mount;
>> -
>> /*
>> * Search to see if name exists, and get back a pointer to it.
>> */
>> - error = xfs_da3_node_lookup_int(state, &retval);
>> - if (error) {
>> + error = xfs_attr_node_hasname(args, &state);
>> + if (error != -EEXIST) {
>> retval = error;
>> goto out_release;
>> }
>> - if (retval != -EEXIST)
>> - goto out_release;
>>
>> /*
>> * Get the value, local or "remote"
>> diff --git a/fs/xfs/libxfs/xfs_attr.h b/fs/xfs/libxfs/xfs_attr.h
>> index cedb4e2..fb56d81 100644
>> --- a/fs/xfs/libxfs/xfs_attr.h
>> +++ b/fs/xfs/libxfs/xfs_attr.h
>> @@ -150,6 +150,7 @@ int xfs_attr_set(struct xfs_inode *dp, struct xfs_name *name,
>> unsigned char *value, int valuelen);
>> int xfs_attr_set_args(struct xfs_da_args *args);
>> int xfs_attr_remove(struct xfs_inode *dp, struct xfs_name *name);
>> +int xfs_has_attr(struct xfs_da_args *args);
>> int xfs_attr_remove_args(struct xfs_da_args *args);
>> int xfs_attr_list(struct xfs_inode *dp, char *buffer, int bufsize,
>> int flags, struct attrlist_cursor_kern *cursor);
>> diff --git a/fs/xfs/libxfs/xfs_attr_leaf.c b/fs/xfs/libxfs/xfs_attr_leaf.c
>> index 07ce320..a501538 100644
>> --- a/fs/xfs/libxfs/xfs_attr_leaf.c
>> +++ b/fs/xfs/libxfs/xfs_attr_leaf.c
>> @@ -590,6 +590,53 @@ xfs_attr_shortform_create(xfs_da_args_t *args)
>> }
>>
>> /*
>> + * Return EEXIST if attr is found, or ENOATTR if not
>> + * args: args containing attribute name and namelen
>> + * sfep: If not null, pointer will be set to the last attr entry found
>> + * basep: If not null, pointer is set to the byte offset of the entry in the
>> + * list
>> + */
>> +int
>> +xfs_shortform_has_attr(
>> + struct xfs_da_args *args,
>> + struct xfs_attr_sf_entry **sfep,
>> + int *basep)
>> +{
>> + struct xfs_attr_shortform *sf;
>> + struct xfs_attr_sf_entry *sfe;
>> + int base = sizeof(struct xfs_attr_sf_hdr);
>> + int size = 0;
>> + int end;
>> + int i;
>> +
>> + base = sizeof(struct xfs_attr_sf_hdr);
>> + sf = (struct xfs_attr_shortform *)args->dp->i_afp->if_u1.if_data;
>> + sfe = &sf->list[0];
>> + end = sf->hdr.count;
>> + for (i = 0; i < end; sfe = XFS_ATTR_SF_NEXTENTRY(sfe),
>> + base += size, i++) {
>> + size = XFS_ATTR_SF_ENTSIZE(sfe);
>> + if (sfe->namelen != args->name.len)
>> + continue;
>> + if (memcmp(sfe->nameval, args->name.name, args->name.len) != 0)
>> + continue;
>> + if (!xfs_attr_namesp_match(args->name.type, sfe->flags))
>> + continue;
>> + break;
>> + }
>> +
>> + if (sfep != NULL)
>> + *sfep = sfe;
>> +
>> + if (basep != NULL)
>> + *basep = base;
>> +
>> + if (i == end)
>> + return -ENOATTR;
>> + return -EEXIST;
>
> This function seems like it could just return a bool. Eh, I suppose it's
> better to be consistent with the other variants if those ones can return
> unrelated errors.
Ok, I prefer the consistency as well.
>
>> +}
>> +
>> +/*
>> * Add a name/value pair to the shortform attribute list.
>> * Overflow from the inode has already been checked for.
>> */
>> @@ -598,7 +645,7 @@ xfs_attr_shortform_add(xfs_da_args_t *args, int forkoff)
>> {
>> xfs_attr_shortform_t *sf;
>> xfs_attr_sf_entry_t *sfe;
>> - int i, offset, size;
>> + int offset, size, error;
>> xfs_mount_t *mp;
>> xfs_inode_t *dp;
>
> Nit: might be good to clean up the typedefs here since you do it in the
> remove function as well.
Sure, will do.
>
>> struct xfs_ifork *ifp;
>> @@ -612,18 +659,10 @@ xfs_attr_shortform_add(xfs_da_args_t *args, int forkoff)
>> ifp = dp->i_afp;
>> ASSERT(ifp->if_flags & XFS_IFINLINE);
>> sf = (xfs_attr_shortform_t *)ifp->if_u1.if_data;
>> - sfe = &sf->list[0];
>> - for (i = 0; i < sf->hdr.count; sfe = XFS_ATTR_SF_NEXTENTRY(sfe), i++) {
>> + error = xfs_shortform_has_attr(args, &sfe, NULL);
>> #ifdef DEBUG
>> - if (sfe->namelen != args->name.len)
>> - continue;
>> - if (memcmp(args->name.name, sfe->nameval, args->name.len) != 0)
>> - continue;
>> - if (!xfs_attr_namesp_match(args->name.type, sfe->flags))
>> - continue;
>> - ASSERT(0);
>> + ASSERT(error != -EEXIST);
>> #endif
>
> Hmm, interesting. So basically this code walks to the end of the list
> for the purpose of placement of the new attr and the debug code simply
> asserts that we don't find an existing attr. The only thing that
> concerns me is that nothing about xfs_shortform_has_attr() indicates
> that the output values are important when the lookup fails. The comment
> only explains what the values are when a lookup succeeds. Could we
> update the comment to elaborate on this use case to prevent somebody
> from unknowingly breaking it down the road?
>
> Also, there's no need for the #ifdef DEBUG any more with just the assert
> check in that block.
Sure, I will clearify the comments and pull out the DEBUG
>
>> - }
>>
>> offset = (char *)sfe - (char *)sf;
>> size = XFS_ATTR_SF_ENTSIZE_BYNAME(args->name.len, args->valuelen);
>> @@ -668,33 +707,24 @@ xfs_attr_fork_remove(
>> int
>> xfs_attr_shortform_remove(xfs_da_args_t *args)
>> {
>> - xfs_attr_shortform_t *sf;
>> - xfs_attr_sf_entry_t *sfe;
>> - int base, size=0, end, totsize, i;
>> - xfs_mount_t *mp;
>> - xfs_inode_t *dp;
>> + struct xfs_attr_shortform *sf;
>> + struct xfs_attr_sf_entry *sfe;
>> + int base, size = 0, end, totsize;
>> + struct xfs_mount *mp;
>> + struct xfs_inode *dp;
>> + int error;
>>
>> trace_xfs_attr_sf_remove(args);
>>
>> dp = args->dp;
>> mp = dp->i_mount;
>> - base = sizeof(xfs_attr_sf_hdr_t);
>> sf = (xfs_attr_shortform_t *)dp->i_afp->if_u1.if_data;
>> - sfe = &sf->list[0];
>> end = sf->hdr.count;
>
> This value of end is unused (end is immediately reassigned further down
> in the function).
>
> Brian
Ok, I will pick that out. Thank you for the thorough reviews!
Allison
>
>> - for (i = 0; i < end; sfe = XFS_ATTR_SF_NEXTENTRY(sfe),
>> - base += size, i++) {
>> - size = XFS_ATTR_SF_ENTSIZE(sfe);
>> - if (sfe->namelen != args->name.len)
>> - continue;
>> - if (memcmp(sfe->nameval, args->name.name, args->name.len) != 0)
>> - continue;
>> - if (!xfs_attr_namesp_match(args->name.type, sfe->flags))
>> - continue;
>> - break;
>> - }
>> - if (i == end)
>> - return -ENOATTR;
>> +
>> + error = xfs_shortform_has_attr(args, &sfe, &base);
>> + if (error == -ENOATTR)
>> + return error;
>> + size = XFS_ATTR_SF_ENTSIZE(sfe);
>>
>> /*
>> * Fix up the attribute fork data, covering the hole
>> diff --git a/fs/xfs/libxfs/xfs_attr_leaf.h b/fs/xfs/libxfs/xfs_attr_leaf.h
>> index 536a290..58e9327 100644
>> --- a/fs/xfs/libxfs/xfs_attr_leaf.h
>> +++ b/fs/xfs/libxfs/xfs_attr_leaf.h
>> @@ -42,6 +42,8 @@ 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_shortform_has_attr(struct xfs_da_args *args,
>> + struct xfs_attr_sf_entry **sfep, int *basep);
>> int xfs_attr_shortform_allfit(struct xfs_buf *bp, struct xfs_inode *dp);
>> int xfs_attr_shortform_bytesfit(struct xfs_inode *dp, int bytes);
>> xfs_failaddr_t xfs_attr_shortform_verify(struct xfs_inode *ip);
>> --
>> 2.7.4
>>
next prev parent reply other threads:[~2019-09-19 23:51 UTC|newest]
Thread overview: 64+ messages / expand[flat|nested] mbox.gz Atom feed top
2019-09-05 22:18 [PATCH v3 00/19] Delayed Attributes Allison Collins
2019-09-05 22:18 ` [PATCH v3 01/19] xfs: Replace attribute parameters with struct xfs_name Allison Collins
2019-09-18 16:43 ` Brian Foster
2019-09-18 18:09 ` Allison Collins
2019-09-18 18:14 ` Brian Foster
2019-09-18 18:48 ` Allison Collins
2019-09-18 19:06 ` Darrick J. Wong
2019-09-05 22:18 ` [PATCH v3 02/19] xfs: Embed struct xfs_name in xfs_da_args Allison Collins
2019-09-18 16:44 ` Brian Foster
2019-09-18 16:47 ` Christoph Hellwig
2019-09-18 19:55 ` Allison Collins
2019-09-05 22:18 ` [PATCH v3 03/19] xfs: Add xfs_dabuf defines Allison Collins
2019-09-06 3:37 ` Darrick J. Wong
2019-09-05 22:18 ` [PATCH v3 04/19] xfs: Add xfs_has_attr and subroutines Allison Collins
2019-09-19 17:47 ` Brian Foster
2019-09-19 23:51 ` Allison Collins [this message]
2019-09-20 12:32 ` Brian Foster
2019-09-05 22:18 ` [PATCH v3 05/19] xfs: Factor out new helper functions xfs_attr_rmtval_set Allison Collins
2019-09-20 13:49 ` Brian Foster
2019-09-21 7:29 ` Allison Collins
2019-09-05 22:18 ` [PATCH v3 06/19] xfs: Factor up trans handling in xfs_attr3_leaf_flipflags Allison Collins
2019-09-20 13:49 ` Brian Foster
2019-09-21 7:00 ` Allison Collins
2019-09-05 22:18 ` [PATCH v3 07/19] xfs: Factor out xfs_attr_leaf_addname helper Allison Collins
2019-09-20 13:49 ` Brian Foster
2019-09-21 7:00 ` Allison Collins
2019-09-05 22:18 ` [PATCH v3 08/19] xfs: Factor up commit from xfs_attr_try_sf_addname Allison Collins
2019-09-20 13:50 ` Brian Foster
2019-09-21 1:25 ` Allison Collins
2019-09-23 12:04 ` Brian Foster
2019-09-05 22:18 ` [PATCH v3 09/19] xfs: Factor up trans roll from xfs_attr3_leaf_setflag Allison Collins
2019-09-20 13:50 ` Brian Foster
2019-09-05 22:18 ` [PATCH v3 10/19] xfs: Add xfs_attr3_leaf helper functions Allison Collins
2019-09-20 13:50 ` Brian Foster
2019-09-21 1:03 ` Allison Collins
2019-09-05 22:18 ` [PATCH v3 11/19] xfs: Factor out xfs_attr_rmtval_invalidate Allison Collins
2019-09-20 13:51 ` Brian Foster
2019-09-20 22:50 ` Allison Collins
2019-09-05 22:18 ` [PATCH v3 12/19] xfs: Factor up trans roll in xfs_attr3_leaf_clearflag Allison Collins
2019-09-20 13:51 ` Brian Foster
2019-09-20 22:49 ` Allison Collins
2019-09-05 22:18 ` [PATCH v3 13/19] xfs: Add delay context to xfs_da_args Allison Collins
2019-09-20 13:51 ` Brian Foster
2019-09-20 22:48 ` Allison Collins
2019-09-05 22:18 ` [PATCH v3 14/19] xfs: Add delayed attribute routines Allison Collins
2019-09-20 15:28 ` Brian Foster
2019-09-20 19:12 ` Allison Collins
2019-09-23 12:04 ` Brian Foster
2019-09-24 5:53 ` Allison Collins
2019-09-24 10:05 ` Brian Foster
2019-09-25 4:36 ` Darrick J. Wong
2019-09-25 11:53 ` Brian Foster
2019-09-25 20:28 ` Allison Collins
2019-09-05 22:18 ` [PATCH v3 15/19] xfs: Set up infastructure for deferred attribute operations Allison Collins
2019-09-05 22:18 ` [PATCH v3 16/19] xfs: Add xfs_attr_set_deferred and xfs_attr_remove_deferred Allison Collins
2019-09-05 22:18 ` [PATCH v3 17/19] xfs: Add feature bit XFS_SB_FEAT_INCOMPAT_LOG_DELATTR Allison Collins
2019-09-05 22:18 ` [PATCH v3 18/19] xfs: Enable delayed attributes Allison Collins
2019-09-05 22:18 ` [PATCH v3 19/19] xfs_io: Add delayed attributes error tag Allison Collins
2019-09-16 12:27 ` [PATCH v3 00/19] Delayed Attributes Brian Foster
2019-09-16 18:41 ` Allison Collins
2019-09-16 19:23 ` Brian Foster
2019-09-16 20:42 ` Allison Collins
2019-09-17 4:43 ` Darrick J. Wong
2019-09-17 12:17 ` Brian Foster
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=de154abf-b2a9-af27-6f1b-e67f19860e62@oracle.com \
--to=allison.henderson@oracle.com \
--cc=bfoster@redhat.com \
--cc=linux-xfs@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox