aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBrian Foster <bfoster@redhat.com>2018-07-12 01:26:22 -0400
committerDarrick J. Wong <darrick.wong@oracle.com>2018-07-12 01:26:22 -0400
commit766139032f95bb41031f6de9c2ee0538bd035229 (patch)
treedc21b2a2b9a56c8ea4dabc3362fccb065e857605
parent825d75cd8c1b53883dd8c2fe1d8833c371b08074 (diff)
xfs: use ->t_firstblock in xattr ops
Similar to the dirops code, the xattr code uses an on-stack firstblock variable for the various operations. This code rolls the underlying transaction in various places, however, which means we cannot simply replace the local firstblock vars with ->t_firstblock. Doing so (without further changes) would invalidate the memory pointed to by xfs_da_args.firstblock as soon as the first transaction rolls. To avoid this problem, remove xfs_da_args.firstblock and replace all such accesses with ->t_firstblock at the same time. This ensures that accesses to the current firstblock always occur through the current transaction rather than a potentially invalid xfs_da_args pointer. Signed-off-by: Brian Foster <bfoster@redhat.com> Reviewed-by: Christoph Hellwig <hch@lst.de> Reviewed-by: Darrick J. Wong <darrick.wong@oracle.com> Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
-rw-r--r--fs/xfs/libxfs/xfs_attr.c37
-rw-r--r--fs/xfs/libxfs/xfs_attr_leaf.c2
-rw-r--r--fs/xfs/libxfs/xfs_attr_remote.c18
-rw-r--r--fs/xfs/libxfs/xfs_bmap.c1
-rw-r--r--fs/xfs/libxfs/xfs_da_btree.c7
-rw-r--r--fs/xfs/libxfs/xfs_da_btree.h1
-rw-r--r--fs/xfs/libxfs/xfs_dir2.c5
7 files changed, 33 insertions, 38 deletions
diff --git a/fs/xfs/libxfs/xfs_attr.c b/fs/xfs/libxfs/xfs_attr.c
index 8a7e2c0308c4..153d2e29f872 100644
--- a/fs/xfs/libxfs/xfs_attr.c
+++ b/fs/xfs/libxfs/xfs_attr.c
@@ -204,7 +204,6 @@ xfs_attr_set(
204 struct xfs_da_args args; 204 struct xfs_da_args args;
205 struct xfs_defer_ops dfops; 205 struct xfs_defer_ops dfops;
206 struct xfs_trans_res tres; 206 struct xfs_trans_res tres;
207 xfs_fsblock_t firstblock;
208 int rsvd = (flags & ATTR_ROOT) != 0; 207 int rsvd = (flags & ATTR_ROOT) != 0;
209 int error, err2, local; 208 int error, err2, local;
210 209
@@ -219,7 +218,6 @@ xfs_attr_set(
219 218
220 args.value = value; 219 args.value = value;
221 args.valuelen = valuelen; 220 args.valuelen = valuelen;
222 args.firstblock = &firstblock;
223 args.op_flags = XFS_DA_OP_ADDNAME | XFS_DA_OP_OKNOENT; 221 args.op_flags = XFS_DA_OP_ADDNAME | XFS_DA_OP_OKNOENT;
224 args.total = xfs_attr_calc_size(&args, &local); 222 args.total = xfs_attr_calc_size(&args, &local);
225 223
@@ -253,7 +251,7 @@ xfs_attr_set(
253 rsvd ? XFS_TRANS_RESERVE : 0, &args.trans); 251 rsvd ? XFS_TRANS_RESERVE : 0, &args.trans);
254 if (error) 252 if (error)
255 return error; 253 return error;
256 xfs_defer_init(args.trans, &dfops, &firstblock); 254 xfs_defer_init(args.trans, &dfops, &args.trans->t_firstblock);
257 255
258 xfs_ilock(dp, XFS_ILOCK_EXCL); 256 xfs_ilock(dp, XFS_ILOCK_EXCL);
259 error = xfs_trans_reserve_quota_nblks(args.trans, dp, args.total, 0, 257 error = xfs_trans_reserve_quota_nblks(args.trans, dp, args.total, 0,
@@ -392,7 +390,6 @@ xfs_attr_remove(
392 struct xfs_mount *mp = dp->i_mount; 390 struct xfs_mount *mp = dp->i_mount;
393 struct xfs_da_args args; 391 struct xfs_da_args args;
394 struct xfs_defer_ops dfops; 392 struct xfs_defer_ops dfops;
395 xfs_fsblock_t firstblock;
396 int error; 393 int error;
397 394
398 XFS_STATS_INC(mp, xs_attr_remove); 395 XFS_STATS_INC(mp, xs_attr_remove);
@@ -404,8 +401,6 @@ xfs_attr_remove(
404 if (error) 401 if (error)
405 return error; 402 return error;
406 403
407 args.firstblock = &firstblock;
408
409 /* 404 /*
410 * we have no control over the attribute names that userspace passes us 405 * we have no control over the attribute names that userspace passes us
411 * to remove, so we have to allow the name lookup prior to attribute 406 * to remove, so we have to allow the name lookup prior to attribute
@@ -427,7 +422,7 @@ xfs_attr_remove(
427 &args.trans); 422 &args.trans);
428 if (error) 423 if (error)
429 return error; 424 return error;
430 xfs_defer_init(args.trans, &dfops, &firstblock); 425 xfs_defer_init(args.trans, &dfops, &args.trans->t_firstblock);
431 426
432 xfs_ilock(dp, XFS_ILOCK_EXCL); 427 xfs_ilock(dp, XFS_ILOCK_EXCL);
433 /* 428 /*
@@ -598,7 +593,8 @@ xfs_attr_leaf_addname(
598 * Commit that transaction so that the node_addname() call 593 * Commit that transaction so that the node_addname() call
599 * can manage its own transactions. 594 * can manage its own transactions.
600 */ 595 */
601 xfs_defer_init(NULL, args->trans->t_dfops, args->firstblock); 596 xfs_defer_init(args->trans, args->trans->t_dfops,
597 &args->trans->t_firstblock);
602 error = xfs_attr3_leaf_to_node(args); 598 error = xfs_attr3_leaf_to_node(args);
603 if (error) 599 if (error)
604 goto out_defer_cancel; 600 goto out_defer_cancel;
@@ -687,8 +683,8 @@ xfs_attr_leaf_addname(
687 * If the result is small enough, shrink it all into the inode. 683 * If the result is small enough, shrink it all into the inode.
688 */ 684 */
689 if ((forkoff = xfs_attr_shortform_allfit(bp, dp))) { 685 if ((forkoff = xfs_attr_shortform_allfit(bp, dp))) {
690 xfs_defer_init(NULL, args->trans->t_dfops, 686 xfs_defer_init(args->trans, args->trans->t_dfops,
691 args->firstblock); 687 &args->trans->t_firstblock);
692 error = xfs_attr3_leaf_to_shortform(bp, args, forkoff); 688 error = xfs_attr3_leaf_to_shortform(bp, args, forkoff);
693 /* bp is gone due to xfs_da_shrink_inode */ 689 /* bp is gone due to xfs_da_shrink_inode */
694 if (error) 690 if (error)
@@ -753,7 +749,8 @@ xfs_attr_leaf_removename(
753 * If the result is small enough, shrink it all into the inode. 749 * If the result is small enough, shrink it all into the inode.
754 */ 750 */
755 if ((forkoff = xfs_attr_shortform_allfit(bp, dp))) { 751 if ((forkoff = xfs_attr_shortform_allfit(bp, dp))) {
756 xfs_defer_init(NULL, args->trans->t_dfops, args->firstblock); 752 xfs_defer_init(args->trans, args->trans->t_dfops,
753 &args->trans->t_firstblock);
757 error = xfs_attr3_leaf_to_shortform(bp, args, forkoff); 754 error = xfs_attr3_leaf_to_shortform(bp, args, forkoff);
758 /* bp is gone due to xfs_da_shrink_inode */ 755 /* bp is gone due to xfs_da_shrink_inode */
759 if (error) 756 if (error)
@@ -882,8 +879,8 @@ restart:
882 */ 879 */
883 xfs_da_state_free(state); 880 xfs_da_state_free(state);
884 state = NULL; 881 state = NULL;
885 xfs_defer_init(NULL, args->trans->t_dfops, 882 xfs_defer_init(args->trans, args->trans->t_dfops,
886 args->firstblock); 883 &args->trans->t_firstblock);
887 error = xfs_attr3_leaf_to_node(args); 884 error = xfs_attr3_leaf_to_node(args);
888 if (error) 885 if (error)
889 goto out_defer_cancel; 886 goto out_defer_cancel;
@@ -910,7 +907,8 @@ restart:
910 * in the index/blkno/rmtblkno/rmtblkcnt fields and 907 * in the index/blkno/rmtblkno/rmtblkcnt fields and
911 * in the index2/blkno2/rmtblkno2/rmtblkcnt2 fields. 908 * in the index2/blkno2/rmtblkno2/rmtblkcnt2 fields.
912 */ 909 */
913 xfs_defer_init(NULL, args->trans->t_dfops, args->firstblock); 910 xfs_defer_init(args->trans, args->trans->t_dfops,
911 &args->trans->t_firstblock);
914 error = xfs_da3_split(state); 912 error = xfs_da3_split(state);
915 if (error) 913 if (error)
916 goto out_defer_cancel; 914 goto out_defer_cancel;
@@ -1008,8 +1006,8 @@ restart:
1008 * Check to see if the tree needs to be collapsed. 1006 * Check to see if the tree needs to be collapsed.
1009 */ 1007 */
1010 if (retval && (state->path.active > 1)) { 1008 if (retval && (state->path.active > 1)) {
1011 xfs_defer_init(NULL, args->trans->t_dfops, 1009 xfs_defer_init(args->trans, args->trans->t_dfops,
1012 args->firstblock); 1010 &args->trans->t_firstblock);
1013 error = xfs_da3_join(state); 1011 error = xfs_da3_join(state);
1014 if (error) 1012 if (error)
1015 goto out_defer_cancel; 1013 goto out_defer_cancel;
@@ -1134,7 +1132,8 @@ xfs_attr_node_removename(
1134 * Check to see if the tree needs to be collapsed. 1132 * Check to see if the tree needs to be collapsed.
1135 */ 1133 */
1136 if (retval && (state->path.active > 1)) { 1134 if (retval && (state->path.active > 1)) {
1137 xfs_defer_init(NULL, args->trans->t_dfops, args->firstblock); 1135 xfs_defer_init(args->trans, args->trans->t_dfops,
1136 &args->trans->t_firstblock);
1138 error = xfs_da3_join(state); 1137 error = xfs_da3_join(state);
1139 if (error) 1138 if (error)
1140 goto out_defer_cancel; 1139 goto out_defer_cancel;
@@ -1166,8 +1165,8 @@ xfs_attr_node_removename(
1166 goto out; 1165 goto out;
1167 1166
1168 if ((forkoff = xfs_attr_shortform_allfit(bp, dp))) { 1167 if ((forkoff = xfs_attr_shortform_allfit(bp, dp))) {
1169 xfs_defer_init(NULL, args->trans->t_dfops, 1168 xfs_defer_init(args->trans, args->trans->t_dfops,
1170 args->firstblock); 1169 &args->trans->t_firstblock);
1171 error = xfs_attr3_leaf_to_shortform(bp, args, forkoff); 1170 error = xfs_attr3_leaf_to_shortform(bp, args, forkoff);
1172 /* bp is gone due to xfs_da_shrink_inode */ 1171 /* bp is gone due to xfs_da_shrink_inode */
1173 if (error) 1172 if (error)
diff --git a/fs/xfs/libxfs/xfs_attr_leaf.c b/fs/xfs/libxfs/xfs_attr_leaf.c
index c131469db0f1..251304f3bc5d 100644
--- a/fs/xfs/libxfs/xfs_attr_leaf.c
+++ b/fs/xfs/libxfs/xfs_attr_leaf.c
@@ -802,7 +802,6 @@ xfs_attr_shortform_to_leaf(
802 memset((char *)&nargs, 0, sizeof(nargs)); 802 memset((char *)&nargs, 0, sizeof(nargs));
803 nargs.dp = dp; 803 nargs.dp = dp;
804 nargs.geo = args->geo; 804 nargs.geo = args->geo;
805 nargs.firstblock = args->firstblock;
806 nargs.total = args->total; 805 nargs.total = args->total;
807 nargs.whichfork = XFS_ATTR_FORK; 806 nargs.whichfork = XFS_ATTR_FORK;
808 nargs.trans = args->trans; 807 nargs.trans = args->trans;
@@ -1005,7 +1004,6 @@ xfs_attr3_leaf_to_shortform(
1005 memset((char *)&nargs, 0, sizeof(nargs)); 1004 memset((char *)&nargs, 0, sizeof(nargs));
1006 nargs.geo = args->geo; 1005 nargs.geo = args->geo;
1007 nargs.dp = dp; 1006 nargs.dp = dp;
1008 nargs.firstblock = args->firstblock;
1009 nargs.total = args->total; 1007 nargs.total = args->total;
1010 nargs.whichfork = XFS_ATTR_FORK; 1008 nargs.whichfork = XFS_ATTR_FORK;
1011 nargs.trans = args->trans; 1009 nargs.trans = args->trans;
diff --git a/fs/xfs/libxfs/xfs_attr_remote.c b/fs/xfs/libxfs/xfs_attr_remote.c
index ab7c2755ad8c..205098aeb4bc 100644
--- a/fs/xfs/libxfs/xfs_attr_remote.c
+++ b/fs/xfs/libxfs/xfs_attr_remote.c
@@ -480,11 +480,13 @@ xfs_attr_rmtval_set(
480 * extent and then crash then the block may not contain the 480 * extent and then crash then the block may not contain the
481 * correct metadata after log recovery occurs. 481 * correct metadata after log recovery occurs.
482 */ 482 */
483 xfs_defer_init(NULL, args->trans->t_dfops, args->firstblock); 483 xfs_defer_init(args->trans, args->trans->t_dfops,
484 &args->trans->t_firstblock);
484 nmap = 1; 485 nmap = 1;
485 error = xfs_bmapi_write(args->trans, dp, (xfs_fileoff_t)lblkno, 486 error = xfs_bmapi_write(args->trans, dp, (xfs_fileoff_t)lblkno,
486 blkcnt, XFS_BMAPI_ATTRFORK, args->firstblock, 487 blkcnt, XFS_BMAPI_ATTRFORK,
487 args->total, &map, &nmap); 488 &args->trans->t_firstblock, args->total, &map,
489 &nmap);
488 if (error) 490 if (error)
489 goto out_defer_cancel; 491 goto out_defer_cancel;
490 xfs_defer_ijoin(args->trans->t_dfops, dp); 492 xfs_defer_ijoin(args->trans->t_dfops, dp);
@@ -522,7 +524,8 @@ xfs_attr_rmtval_set(
522 524
523 ASSERT(blkcnt > 0); 525 ASSERT(blkcnt > 0);
524 526
525 xfs_defer_init(NULL, args->trans->t_dfops, args->firstblock); 527 xfs_defer_init(args->trans, args->trans->t_dfops,
528 &args->trans->t_firstblock);
526 nmap = 1; 529 nmap = 1;
527 error = xfs_bmapi_read(dp, (xfs_fileoff_t)lblkno, 530 error = xfs_bmapi_read(dp, (xfs_fileoff_t)lblkno,
528 blkcnt, &map, &nmap, 531 blkcnt, &map, &nmap,
@@ -626,10 +629,11 @@ xfs_attr_rmtval_remove(
626 blkcnt = args->rmtblkcnt; 629 blkcnt = args->rmtblkcnt;
627 done = 0; 630 done = 0;
628 while (!done) { 631 while (!done) {
629 xfs_defer_init(NULL, args->trans->t_dfops, args->firstblock); 632 xfs_defer_init(args->trans, args->trans->t_dfops,
633 &args->trans->t_firstblock);
630 error = xfs_bunmapi(args->trans, args->dp, lblkno, blkcnt, 634 error = xfs_bunmapi(args->trans, args->dp, lblkno, blkcnt,
631 XFS_BMAPI_ATTRFORK, 1, args->firstblock, 635 XFS_BMAPI_ATTRFORK, 1,
632 &done); 636 &args->trans->t_firstblock, &done);
633 if (error) 637 if (error)
634 goto out_defer_cancel; 638 goto out_defer_cancel;
635 xfs_defer_ijoin(args->trans->t_dfops, args->dp); 639 xfs_defer_ijoin(args->trans->t_dfops, args->dp);
diff --git a/fs/xfs/libxfs/xfs_bmap.c b/fs/xfs/libxfs/xfs_bmap.c
index da73c1a011d3..6f9b2cddb933 100644
--- a/fs/xfs/libxfs/xfs_bmap.c
+++ b/fs/xfs/libxfs/xfs_bmap.c
@@ -1000,7 +1000,6 @@ xfs_bmap_add_attrfork_local(
1000 memset(&dargs, 0, sizeof(dargs)); 1000 memset(&dargs, 0, sizeof(dargs));
1001 dargs.geo = ip->i_mount->m_dir_geo; 1001 dargs.geo = ip->i_mount->m_dir_geo;
1002 dargs.dp = ip; 1002 dargs.dp = ip;
1003 dargs.firstblock = &tp->t_firstblock;
1004 dargs.total = dargs.geo->fsbcount; 1003 dargs.total = dargs.geo->fsbcount;
1005 dargs.whichfork = XFS_DATA_FORK; 1004 dargs.whichfork = XFS_DATA_FORK;
1006 dargs.trans = tp; 1005 dargs.trans = tp;
diff --git a/fs/xfs/libxfs/xfs_da_btree.c b/fs/xfs/libxfs/xfs_da_btree.c
index 68a72e3d9f53..2f2be86c10dc 100644
--- a/fs/xfs/libxfs/xfs_da_btree.c
+++ b/fs/xfs/libxfs/xfs_da_btree.c
@@ -2059,10 +2059,9 @@ xfs_da_grow_inode_int(
2059 * Try mapping it in one filesystem block. 2059 * Try mapping it in one filesystem block.
2060 */ 2060 */
2061 nmap = 1; 2061 nmap = 1;
2062 ASSERT(args->firstblock != NULL);
2063 error = xfs_bmapi_write(tp, dp, *bno, count, 2062 error = xfs_bmapi_write(tp, dp, *bno, count,
2064 xfs_bmapi_aflag(w)|XFS_BMAPI_METADATA|XFS_BMAPI_CONTIG, 2063 xfs_bmapi_aflag(w)|XFS_BMAPI_METADATA|XFS_BMAPI_CONTIG,
2065 args->firstblock, args->total, &map, &nmap); 2064 &tp->t_firstblock, args->total, &map, &nmap);
2066 if (error) 2065 if (error)
2067 return error; 2066 return error;
2068 2067
@@ -2084,7 +2083,7 @@ xfs_da_grow_inode_int(
2084 c = (int)(*bno + count - b); 2083 c = (int)(*bno + count - b);
2085 error = xfs_bmapi_write(tp, dp, b, c, 2084 error = xfs_bmapi_write(tp, dp, b, c,
2086 xfs_bmapi_aflag(w)|XFS_BMAPI_METADATA, 2085 xfs_bmapi_aflag(w)|XFS_BMAPI_METADATA,
2087 args->firstblock, args->total, 2086 &tp->t_firstblock, args->total,
2088 &mapp[mapi], &nmap); 2087 &mapp[mapi], &nmap);
2089 if (error) 2088 if (error)
2090 goto out_free_map; 2089 goto out_free_map;
@@ -2394,7 +2393,7 @@ xfs_da_shrink_inode(
2394 * the last block to the place we want to kill. 2393 * the last block to the place we want to kill.
2395 */ 2394 */
2396 error = xfs_bunmapi(tp, dp, dead_blkno, count, 2395 error = xfs_bunmapi(tp, dp, dead_blkno, count,
2397 xfs_bmapi_aflag(w), 0, args->firstblock, 2396 xfs_bmapi_aflag(w), 0, &tp->t_firstblock,
2398 &done); 2397 &done);
2399 if (error == -ENOSPC) { 2398 if (error == -ENOSPC) {
2400 if (w != XFS_DATA_FORK) 2399 if (w != XFS_DATA_FORK)
diff --git a/fs/xfs/libxfs/xfs_da_btree.h b/fs/xfs/libxfs/xfs_da_btree.h
index 6b8a04f3f162..59e290ef334f 100644
--- a/fs/xfs/libxfs/xfs_da_btree.h
+++ b/fs/xfs/libxfs/xfs_da_btree.h
@@ -57,7 +57,6 @@ typedef struct xfs_da_args {
57 xfs_dahash_t hashval; /* hash value of name */ 57 xfs_dahash_t hashval; /* hash value of name */
58 xfs_ino_t inumber; /* input/output inode number */ 58 xfs_ino_t inumber; /* input/output inode number */
59 struct xfs_inode *dp; /* directory inode to manipulate */ 59 struct xfs_inode *dp; /* directory inode to manipulate */
60 xfs_fsblock_t *firstblock; /* ptr to firstblock for bmap calls */
61 struct xfs_trans *trans; /* current trans (changes over time) */ 60 struct xfs_trans *trans; /* current trans (changes over time) */
62 xfs_extlen_t total; /* total blocks needed, for 1st bmap */ 61 xfs_extlen_t total; /* total blocks needed, for 1st bmap */
63 int whichfork; /* data or attribute fork */ 62 int whichfork; /* data or attribute fork */
diff --git a/fs/xfs/libxfs/xfs_dir2.c b/fs/xfs/libxfs/xfs_dir2.c
index a3983e3eb64a..5db73d96b99e 100644
--- a/fs/xfs/libxfs/xfs_dir2.c
+++ b/fs/xfs/libxfs/xfs_dir2.c
@@ -272,7 +272,6 @@ xfs_dir_createname(
272 args->total = total; 272 args->total = total;
273 args->whichfork = XFS_DATA_FORK; 273 args->whichfork = XFS_DATA_FORK;
274 args->trans = tp; 274 args->trans = tp;
275 args->firstblock = &tp->t_firstblock;
276 args->op_flags = XFS_DA_OP_ADDNAME | XFS_DA_OP_OKNOENT; 275 args->op_flags = XFS_DA_OP_ADDNAME | XFS_DA_OP_OKNOENT;
277 if (!inum) 276 if (!inum)
278 args->op_flags |= XFS_DA_OP_JUSTCHECK; 277 args->op_flags |= XFS_DA_OP_JUSTCHECK;
@@ -439,7 +438,6 @@ xfs_dir_removename(
439 args->hashval = dp->i_mount->m_dirnameops->hashname(name); 438 args->hashval = dp->i_mount->m_dirnameops->hashname(name);
440 args->inumber = ino; 439 args->inumber = ino;
441 args->dp = dp; 440 args->dp = dp;
442 args->firstblock = &tp->t_firstblock;
443 args->total = total; 441 args->total = total;
444 args->whichfork = XFS_DATA_FORK; 442 args->whichfork = XFS_DATA_FORK;
445 args->trans = tp; 443 args->trans = tp;
@@ -502,7 +500,6 @@ xfs_dir_replace(
502 args->hashval = dp->i_mount->m_dirnameops->hashname(name); 500 args->hashval = dp->i_mount->m_dirnameops->hashname(name);
503 args->inumber = inum; 501 args->inumber = inum;
504 args->dp = dp; 502 args->dp = dp;
505 args->firstblock = &tp->t_firstblock;
506 args->total = total; 503 args->total = total;
507 args->whichfork = XFS_DATA_FORK; 504 args->whichfork = XFS_DATA_FORK;
508 args->trans = tp; 505 args->trans = tp;
@@ -660,7 +657,7 @@ xfs_dir2_shrink_inode(
660 657
661 /* Unmap the fsblock(s). */ 658 /* Unmap the fsblock(s). */
662 error = xfs_bunmapi(tp, dp, da, args->geo->fsbcount, 0, 0, 659 error = xfs_bunmapi(tp, dp, da, args->geo->fsbcount, 0, 0,
663 args->firstblock, &done); 660 &tp->t_firstblock, &done);
664 if (error) { 661 if (error) {
665 /* 662 /*
666 * ENOSPC actually can happen if we're in a removename with no 663 * ENOSPC actually can happen if we're in a removename with no