Skip to content

Commit 07120f1

Browse files
allisonhendersondjwong
authored andcommitted
xfs: Add xfs_has_attr and subroutines
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 appearance of duplicated code. We will need these routines later for delayed attributes since delayed operations cannot return error codes. Signed-off-by: Allison Collins <[email protected]> Reviewed-by: Chandan Rajendra <[email protected]> Reviewed-by: Brian Foster <[email protected]> Reviewed-by: Darrick J. Wong <[email protected]> [darrick: fix a leak-on-error bug reported by Dan Carpenter] [darrick: fix unused variable warning reported by 0day] Signed-off-by: Darrick J. Wong <[email protected]> Acked-by: Dave Chinner <[email protected]> Reported-by: [email protected] Reported-by: kernel test robot <[email protected]>
1 parent 4491a3d commit 07120f1

File tree

4 files changed

+197
-91
lines changed

4 files changed

+197
-91
lines changed

fs/xfs/libxfs/xfs_attr.c

Lines changed: 123 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -46,13 +46,16 @@ STATIC int xfs_attr_shortform_addname(xfs_da_args_t *args);
4646
STATIC int xfs_attr_leaf_get(xfs_da_args_t *args);
4747
STATIC int xfs_attr_leaf_addname(xfs_da_args_t *args);
4848
STATIC int xfs_attr_leaf_removename(xfs_da_args_t *args);
49+
STATIC int xfs_attr_leaf_hasname(struct xfs_da_args *args, struct xfs_buf **bp);
4950

5051
/*
5152
* Internal routines when attribute list is more than one block.
5253
*/
5354
STATIC int xfs_attr_node_get(xfs_da_args_t *args);
5455
STATIC int xfs_attr_node_addname(xfs_da_args_t *args);
5556
STATIC int xfs_attr_node_removename(xfs_da_args_t *args);
57+
STATIC int xfs_attr_node_hasname(xfs_da_args_t *args,
58+
struct xfs_da_state **state);
5659
STATIC int xfs_attr_fillstate(xfs_da_state_t *state);
5760
STATIC int xfs_attr_refillstate(xfs_da_state_t *state);
5861

@@ -260,6 +263,37 @@ xfs_attr_set_args(
260263
return error;
261264
}
262265

266+
/*
267+
* Return EEXIST if attr is found, or ENOATTR if not
268+
*/
269+
int
270+
xfs_has_attr(
271+
struct xfs_da_args *args)
272+
{
273+
struct xfs_inode *dp = args->dp;
274+
struct xfs_buf *bp = NULL;
275+
int error;
276+
277+
if (!xfs_inode_hasattr(dp))
278+
return -ENOATTR;
279+
280+
if (dp->i_afp->if_format == XFS_DINODE_FMT_LOCAL) {
281+
ASSERT(dp->i_afp->if_flags & XFS_IFINLINE);
282+
return xfs_attr_sf_findname(args, NULL, NULL);
283+
}
284+
285+
if (xfs_bmap_one_block(dp, XFS_ATTR_FORK)) {
286+
error = xfs_attr_leaf_hasname(args, &bp);
287+
288+
if (bp)
289+
xfs_trans_brelse(args->trans, bp);
290+
291+
return error;
292+
}
293+
294+
return xfs_attr_node_hasname(args, NULL);
295+
}
296+
263297
/*
264298
* Remove the attribute specified in @args.
265299
*/
@@ -469,26 +503,19 @@ STATIC int
469503
xfs_attr_leaf_addname(
470504
struct xfs_da_args *args)
471505
{
472-
struct xfs_inode *dp;
473506
struct xfs_buf *bp;
474507
int retval, error, forkoff;
508+
struct xfs_inode *dp = args->dp;
475509

476510
trace_xfs_attr_leaf_addname(args);
477511

478-
/*
479-
* Read the (only) block in the attribute list in.
480-
*/
481-
dp = args->dp;
482-
args->blkno = 0;
483-
error = xfs_attr3_leaf_read(args->trans, args->dp, args->blkno, &bp);
484-
if (error)
485-
return error;
486-
487512
/*
488513
* Look up the given attribute in the leaf block. Figure out if
489514
* the given flags produce an error or call for an atomic rename.
490515
*/
491-
retval = xfs_attr3_leaf_lookup_int(bp, args);
516+
retval = xfs_attr_leaf_hasname(args, &bp);
517+
if (retval != -ENOATTR && retval != -EEXIST)
518+
return retval;
492519
if (retval == -ENOATTR && (args->attr_flags & XATTR_REPLACE))
493520
goto out_brelse;
494521
if (retval == -EEXIST) {
@@ -639,6 +666,27 @@ xfs_attr_leaf_addname(
639666
return retval;
640667
}
641668

669+
/*
670+
* Return EEXIST if attr is found, or ENOATTR if not
671+
*/
672+
STATIC int
673+
xfs_attr_leaf_hasname(
674+
struct xfs_da_args *args,
675+
struct xfs_buf **bp)
676+
{
677+
int error = 0;
678+
679+
error = xfs_attr3_leaf_read(args->trans, args->dp, 0, bp);
680+
if (error)
681+
return error;
682+
683+
error = xfs_attr3_leaf_lookup_int(*bp, args);
684+
if (error != -ENOATTR && error != -EEXIST)
685+
xfs_trans_brelse(args->trans, *bp);
686+
687+
return error;
688+
}
689+
642690
/*
643691
* Remove a name from the leaf attribute list structure
644692
*
@@ -659,16 +707,14 @@ xfs_attr_leaf_removename(
659707
* Remove the attribute.
660708
*/
661709
dp = args->dp;
662-
args->blkno = 0;
663-
error = xfs_attr3_leaf_read(args->trans, args->dp, args->blkno, &bp);
664-
if (error)
665-
return error;
666710

667-
error = xfs_attr3_leaf_lookup_int(bp, args);
711+
error = xfs_attr_leaf_hasname(args, &bp);
712+
668713
if (error == -ENOATTR) {
669714
xfs_trans_brelse(args->trans, bp);
670715
return error;
671-
}
716+
} else if (error != -EEXIST)
717+
return error;
672718

673719
xfs_attr3_leaf_remove(bp, args);
674720

@@ -703,21 +749,53 @@ xfs_attr_leaf_get(xfs_da_args_t *args)
703749

704750
trace_xfs_attr_leaf_get(args);
705751

706-
args->blkno = 0;
707-
error = xfs_attr3_leaf_read(args->trans, args->dp, args->blkno, &bp);
708-
if (error)
709-
return error;
752+
error = xfs_attr_leaf_hasname(args, &bp);
710753

711-
error = xfs_attr3_leaf_lookup_int(bp, args);
712-
if (error != -EEXIST) {
754+
if (error == -ENOATTR) {
713755
xfs_trans_brelse(args->trans, bp);
714756
return error;
715-
}
757+
} else if (error != -EEXIST)
758+
return error;
759+
760+
716761
error = xfs_attr3_leaf_getvalue(bp, args);
717762
xfs_trans_brelse(args->trans, bp);
718763
return error;
719764
}
720765

766+
/*
767+
* Return EEXIST if attr is found, or ENOATTR if not
768+
* statep: If not null is set to point at the found state. Caller will
769+
* be responsible for freeing the state in this case.
770+
*/
771+
STATIC int
772+
xfs_attr_node_hasname(
773+
struct xfs_da_args *args,
774+
struct xfs_da_state **statep)
775+
{
776+
struct xfs_da_state *state;
777+
int retval, error;
778+
779+
state = xfs_da_state_alloc(args);
780+
if (statep != NULL)
781+
*statep = NULL;
782+
783+
/*
784+
* Search to see if name exists, and get back a pointer to it.
785+
*/
786+
error = xfs_da3_node_lookup_int(state, &retval);
787+
if (error) {
788+
xfs_da_state_free(state);
789+
return error;
790+
}
791+
792+
if (statep != NULL)
793+
*statep = state;
794+
else
795+
xfs_da_state_free(state);
796+
return retval;
797+
}
798+
721799
/*========================================================================
722800
* External routines when attribute list size > geo->blksize
723801
*========================================================================*/
@@ -748,15 +826,14 @@ xfs_attr_node_addname(
748826
*/
749827
dp = args->dp;
750828
restart:
751-
state = xfs_da_state_alloc(args);
752-
753829
/*
754830
* Search to see if name already exists, and get back a pointer
755831
* to where it should go.
756832
*/
757-
error = xfs_da3_node_lookup_int(state, &retval);
758-
if (error)
833+
retval = xfs_attr_node_hasname(args, &state);
834+
if (retval != -ENOATTR && retval != -EEXIST)
759835
goto out;
836+
760837
blk = &state->path.blk[ state->path.active-1 ];
761838
ASSERT(blk->magic == XFS_ATTR_LEAF_MAGIC);
762839
if (retval == -ENOATTR && (args->attr_flags & XATTR_REPLACE))
@@ -960,27 +1037,15 @@ xfs_attr_node_removename(
9601037
{
9611038
struct xfs_da_state *state;
9621039
struct xfs_da_state_blk *blk;
963-
struct xfs_inode *dp;
9641040
struct xfs_buf *bp;
9651041
int retval, error, forkoff;
1042+
struct xfs_inode *dp = args->dp;
9661043

9671044
trace_xfs_attr_node_removename(args);
9681045

969-
/*
970-
* Tie a string around our finger to remind us where we are.
971-
*/
972-
dp = args->dp;
973-
state = xfs_da_state_alloc(args);
974-
975-
/*
976-
* Search to see if name exists, and get back a pointer to it.
977-
*/
978-
error = xfs_da3_node_lookup_int(state, &retval);
979-
if (error || (retval != -EEXIST)) {
980-
if (error == 0)
981-
error = retval;
1046+
error = xfs_attr_node_hasname(args, &state);
1047+
if (error != -EEXIST)
9821048
goto out;
983-
}
9841049

9851050
/*
9861051
* If there is an out-of-line value, de-allocate the blocks.
@@ -1075,7 +1140,8 @@ xfs_attr_node_removename(
10751140
error = 0;
10761141

10771142
out:
1078-
xfs_da_state_free(state);
1143+
if (state)
1144+
xfs_da_state_free(state);
10791145
return error;
10801146
}
10811147

@@ -1191,45 +1257,41 @@ xfs_attr_refillstate(xfs_da_state_t *state)
11911257
* Returns 0 on successful retrieval, otherwise an error.
11921258
*/
11931259
STATIC int
1194-
xfs_attr_node_get(xfs_da_args_t *args)
1260+
xfs_attr_node_get(
1261+
struct xfs_da_args *args)
11951262
{
1196-
xfs_da_state_t *state;
1197-
xfs_da_state_blk_t *blk;
1198-
int error, retval;
1199-
int i;
1263+
struct xfs_da_state *state;
1264+
struct xfs_da_state_blk *blk;
1265+
int i;
1266+
int error;
12001267

12011268
trace_xfs_attr_node_get(args);
12021269

1203-
state = xfs_da_state_alloc(args);
1204-
12051270
/*
12061271
* Search to see if name exists, and get back a pointer to it.
12071272
*/
1208-
error = xfs_da3_node_lookup_int(state, &retval);
1209-
if (error) {
1210-
retval = error;
1211-
goto out_release;
1212-
}
1213-
if (retval != -EEXIST)
1273+
error = xfs_attr_node_hasname(args, &state);
1274+
if (error != -EEXIST)
12141275
goto out_release;
12151276

12161277
/*
12171278
* Get the value, local or "remote"
12181279
*/
12191280
blk = &state->path.blk[state->path.active - 1];
1220-
retval = xfs_attr3_leaf_getvalue(blk->bp, args);
1281+
error = xfs_attr3_leaf_getvalue(blk->bp, args);
12211282

12221283
/*
12231284
* If not in a transaction, we have to release all the buffers.
12241285
*/
12251286
out_release:
1226-
for (i = 0; i < state->path.active; i++) {
1287+
for (i = 0; state != NULL && i < state->path.active; i++) {
12271288
xfs_trans_brelse(args->trans, state->path.blk[i].bp);
12281289
state->path.blk[i].bp = NULL;
12291290
}
12301291

1231-
xfs_da_state_free(state);
1232-
return retval;
1292+
if (state)
1293+
xfs_da_state_free(state);
1294+
return error;
12331295
}
12341296

12351297
/* Returns true if the attribute entry name is valid. */

fs/xfs/libxfs/xfs_attr.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ int xfs_attr_get_ilocked(struct xfs_da_args *args);
8989
int xfs_attr_get(struct xfs_da_args *args);
9090
int xfs_attr_set(struct xfs_da_args *args);
9191
int xfs_attr_set_args(struct xfs_da_args *args);
92+
int xfs_has_attr(struct xfs_da_args *args);
9293
int xfs_attr_remove_args(struct xfs_da_args *args);
9394
bool xfs_attr_namecheck(const void *name, size_t length);
9495

0 commit comments

Comments
 (0)