Skip to content

Commit 3577cfd

Browse files
committed
Merge tag 'xfs-fixes-7.0-rc6' of git://git.kernel.org/pub/scm/fs/xfs/xfs-linux
Pull xfs fixes from Carlos Maiolino: "This includes a few important bug fixes, and some code refactoring that was necessary for one of the fixes" * tag 'xfs-fixes-7.0-rc6' of git://git.kernel.org/pub/scm/fs/xfs/xfs-linux: xfs: remove file_path tracepoint data xfs: don't irele after failing to iget in xfs_attri_recover_work xfs: remove redundant validation in xlog_recover_attri_commit_pass2 xfs: fix ri_total validation in xlog_recover_attri_commit_pass2 xfs: close crash window in attr dabtree inactivation xfs: factor out xfs_attr3_leaf_init xfs: factor out xfs_attr3_node_entry_remove xfs: only assert new size for datafork during truncate extents xfs: annotate struct xfs_attr_list_context with __counted_by_ptr xfs: cleanup buftarg handling in XFS_IOC_VERIFY_MEDIA xfs: scrub: unlock dquot before early return in quota scrub xfs: refactor xfsaild_push loop into helper xfs: save ailp before dropping the AIL lock in push callbacks xfs: avoid dereferencing log items after push callbacks xfs: stop reclaim before pushing AIL during unmount
2 parents 3489299 + e31c53a commit 3577cfd

18 files changed

Lines changed: 274 additions & 195 deletions

fs/xfs/libxfs/xfs_attr.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,8 @@ struct xfs_attr_list_context {
5555
struct xfs_trans *tp;
5656
struct xfs_inode *dp; /* inode */
5757
struct xfs_attrlist_cursor_kern cursor; /* position in list */
58-
void *buffer; /* output buffer */
58+
/* output buffer */
59+
void *buffer __counted_by_ptr(bufsize);
5960

6061
/*
6162
* Abort attribute list iteration if non-zero. Can be used to pass

fs/xfs/libxfs/xfs_attr_leaf.c

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1415,6 +1415,28 @@ xfs_attr3_leaf_create(
14151415
return 0;
14161416
}
14171417

1418+
/*
1419+
* Reinitialize an existing attr fork block as an empty leaf, and attach
1420+
* the buffer to tp.
1421+
*/
1422+
int
1423+
xfs_attr3_leaf_init(
1424+
struct xfs_trans *tp,
1425+
struct xfs_inode *dp,
1426+
xfs_dablk_t blkno)
1427+
{
1428+
struct xfs_buf *bp = NULL;
1429+
struct xfs_da_args args = {
1430+
.trans = tp,
1431+
.dp = dp,
1432+
.owner = dp->i_ino,
1433+
.geo = dp->i_mount->m_attr_geo,
1434+
};
1435+
1436+
ASSERT(tp != NULL);
1437+
1438+
return xfs_attr3_leaf_create(&args, blkno, &bp);
1439+
}
14181440
/*
14191441
* Split the leaf node, rebalance, then add the new entry.
14201442
*

fs/xfs/libxfs/xfs_attr_leaf.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,9 @@ int xfs_attr3_leaf_list_int(struct xfs_buf *bp,
8787
/*
8888
* Routines used for shrinking the Btree.
8989
*/
90+
91+
int xfs_attr3_leaf_init(struct xfs_trans *tp, struct xfs_inode *dp,
92+
xfs_dablk_t blkno);
9093
int xfs_attr3_leaf_toosmall(struct xfs_da_state *state, int *retval);
9194
void xfs_attr3_leaf_unbalance(struct xfs_da_state *state,
9295
struct xfs_da_state_blk *drop_blk,

fs/xfs/libxfs/xfs_da_btree.c

Lines changed: 42 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1506,21 +1506,20 @@ xfs_da3_fixhashpath(
15061506
}
15071507

15081508
/*
1509-
* Remove an entry from an intermediate node.
1509+
* Internal implementation to remove an entry from an intermediate node.
15101510
*/
15111511
STATIC void
1512-
xfs_da3_node_remove(
1513-
struct xfs_da_state *state,
1514-
struct xfs_da_state_blk *drop_blk)
1512+
__xfs_da3_node_remove(
1513+
struct xfs_trans *tp,
1514+
struct xfs_inode *dp,
1515+
struct xfs_da_geometry *geo,
1516+
struct xfs_da_state_blk *drop_blk)
15151517
{
15161518
struct xfs_da_intnode *node;
15171519
struct xfs_da3_icnode_hdr nodehdr;
15181520
struct xfs_da_node_entry *btree;
15191521
int index;
15201522
int tmp;
1521-
struct xfs_inode *dp = state->args->dp;
1522-
1523-
trace_xfs_da_node_remove(state->args);
15241523

15251524
node = drop_blk->bp->b_addr;
15261525
xfs_da3_node_hdr_from_disk(dp->i_mount, &nodehdr, node);
@@ -1536,24 +1535,56 @@ xfs_da3_node_remove(
15361535
tmp = nodehdr.count - index - 1;
15371536
tmp *= (uint)sizeof(xfs_da_node_entry_t);
15381537
memmove(&btree[index], &btree[index + 1], tmp);
1539-
xfs_trans_log_buf(state->args->trans, drop_blk->bp,
1538+
xfs_trans_log_buf(tp, drop_blk->bp,
15401539
XFS_DA_LOGRANGE(node, &btree[index], tmp));
15411540
index = nodehdr.count - 1;
15421541
}
15431542
memset(&btree[index], 0, sizeof(xfs_da_node_entry_t));
1544-
xfs_trans_log_buf(state->args->trans, drop_blk->bp,
1543+
xfs_trans_log_buf(tp, drop_blk->bp,
15451544
XFS_DA_LOGRANGE(node, &btree[index], sizeof(btree[index])));
15461545
nodehdr.count -= 1;
15471546
xfs_da3_node_hdr_to_disk(dp->i_mount, node, &nodehdr);
1548-
xfs_trans_log_buf(state->args->trans, drop_blk->bp,
1549-
XFS_DA_LOGRANGE(node, &node->hdr, state->args->geo->node_hdr_size));
1547+
xfs_trans_log_buf(tp, drop_blk->bp,
1548+
XFS_DA_LOGRANGE(node, &node->hdr, geo->node_hdr_size));
15501549

15511550
/*
15521551
* Copy the last hash value from the block to propagate upwards.
15531552
*/
15541553
drop_blk->hashval = be32_to_cpu(btree[index - 1].hashval);
15551554
}
15561555

1556+
/*
1557+
* Remove an entry from an intermediate node.
1558+
*/
1559+
STATIC void
1560+
xfs_da3_node_remove(
1561+
struct xfs_da_state *state,
1562+
struct xfs_da_state_blk *drop_blk)
1563+
{
1564+
trace_xfs_da_node_remove(state->args);
1565+
1566+
__xfs_da3_node_remove(state->args->trans, state->args->dp,
1567+
state->args->geo, drop_blk);
1568+
}
1569+
1570+
/*
1571+
* Remove an entry from an intermediate attr node at the specified index.
1572+
*/
1573+
void
1574+
xfs_attr3_node_entry_remove(
1575+
struct xfs_trans *tp,
1576+
struct xfs_inode *dp,
1577+
struct xfs_buf *bp,
1578+
int index)
1579+
{
1580+
struct xfs_da_state_blk blk = {
1581+
.index = index,
1582+
.bp = bp,
1583+
};
1584+
1585+
__xfs_da3_node_remove(tp, dp, dp->i_mount->m_attr_geo, &blk);
1586+
}
1587+
15571588
/*
15581589
* Unbalance the elements between two intermediate nodes,
15591590
* move all Btree elements from one node into another.

fs/xfs/libxfs/xfs_da_btree.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,8 @@ int xfs_da3_split(xfs_da_state_t *state);
184184
int xfs_da3_join(xfs_da_state_t *state);
185185
void xfs_da3_fixhashpath(struct xfs_da_state *state,
186186
struct xfs_da_state_path *path_to_to_fix);
187+
void xfs_attr3_node_entry_remove(struct xfs_trans *tp, struct xfs_inode *dp,
188+
struct xfs_buf *bp, int index);
187189

188190
/*
189191
* Routines used for finding things in the Btree.

fs/xfs/scrub/quota.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -171,8 +171,10 @@ xchk_quota_item(
171171

172172
error = xchk_quota_item_bmap(sc, dq, offset);
173173
xchk_iunlock(sc, XFS_ILOCK_SHARED);
174-
if (!xchk_fblock_process_error(sc, XFS_DATA_FORK, offset, &error))
174+
if (!xchk_fblock_process_error(sc, XFS_DATA_FORK, offset, &error)) {
175+
mutex_unlock(&dq->q_qlock);
175176
return error;
177+
}
176178

177179
/*
178180
* Warn if the hard limits are larger than the fs.

fs/xfs/scrub/trace.h

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -972,20 +972,12 @@ TRACE_EVENT(xfile_create,
972972
TP_STRUCT__entry(
973973
__field(dev_t, dev)
974974
__field(unsigned long, ino)
975-
__array(char, pathname, MAXNAMELEN)
976975
),
977976
TP_fast_assign(
978-
char *path;
979-
980977
__entry->ino = file_inode(xf->file)->i_ino;
981-
path = file_path(xf->file, __entry->pathname, MAXNAMELEN);
982-
if (IS_ERR(path))
983-
strncpy(__entry->pathname, "(unknown)",
984-
sizeof(__entry->pathname));
985978
),
986-
TP_printk("xfino 0x%lx path '%s'",
987-
__entry->ino,
988-
__entry->pathname)
979+
TP_printk("xfino 0x%lx",
980+
__entry->ino)
989981
);
990982

991983
TRACE_EVENT(xfile_destroy,

fs/xfs/xfs_attr_inactive.c

Lines changed: 57 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ xfs_attr3_node_inactive(
140140
xfs_daddr_t parent_blkno, child_blkno;
141141
struct xfs_buf *child_bp;
142142
struct xfs_da3_icnode_hdr ichdr;
143-
int error, i;
143+
int error;
144144

145145
/*
146146
* Since this code is recursive (gasp!) we must protect ourselves.
@@ -152,7 +152,7 @@ xfs_attr3_node_inactive(
152152
return -EFSCORRUPTED;
153153
}
154154

155-
xfs_da3_node_hdr_from_disk(dp->i_mount, &ichdr, bp->b_addr);
155+
xfs_da3_node_hdr_from_disk(mp, &ichdr, bp->b_addr);
156156
parent_blkno = xfs_buf_daddr(bp);
157157
if (!ichdr.count) {
158158
xfs_trans_brelse(*trans, bp);
@@ -167,7 +167,7 @@ xfs_attr3_node_inactive(
167167
* over the leaves removing all of them. If this is higher up
168168
* in the tree, recurse downward.
169169
*/
170-
for (i = 0; i < ichdr.count; i++) {
170+
while (ichdr.count > 0) {
171171
/*
172172
* Read the subsidiary block to see what we have to work with.
173173
* Don't do this in a transaction. This is a depth-first
@@ -218,29 +218,32 @@ xfs_attr3_node_inactive(
218218
xfs_trans_binval(*trans, child_bp);
219219
child_bp = NULL;
220220

221+
error = xfs_da3_node_read_mapped(*trans, dp,
222+
parent_blkno, &bp, XFS_ATTR_FORK);
223+
if (error)
224+
return error;
225+
221226
/*
222-
* If we're not done, re-read the parent to get the next
223-
* child block number.
227+
* Remove entry from parent node, prevents being indexed to.
224228
*/
225-
if (i + 1 < ichdr.count) {
226-
struct xfs_da3_icnode_hdr phdr;
229+
xfs_attr3_node_entry_remove(*trans, dp, bp, 0);
230+
231+
xfs_da3_node_hdr_from_disk(mp, &ichdr, bp->b_addr);
232+
bp = NULL;
227233

228-
error = xfs_da3_node_read_mapped(*trans, dp,
229-
parent_blkno, &bp, XFS_ATTR_FORK);
234+
if (ichdr.count > 0) {
235+
/*
236+
* If we're not done, get the next child block number.
237+
*/
238+
child_fsb = be32_to_cpu(ichdr.btree[0].before);
239+
240+
/*
241+
* Atomically commit the whole invalidate stuff.
242+
*/
243+
error = xfs_trans_roll_inode(trans, dp);
230244
if (error)
231245
return error;
232-
xfs_da3_node_hdr_from_disk(dp->i_mount, &phdr,
233-
bp->b_addr);
234-
child_fsb = be32_to_cpu(phdr.btree[i + 1].before);
235-
xfs_trans_brelse(*trans, bp);
236-
bp = NULL;
237246
}
238-
/*
239-
* Atomically commit the whole invalidate stuff.
240-
*/
241-
error = xfs_trans_roll_inode(trans, dp);
242-
if (error)
243-
return error;
244247
}
245248

246249
return 0;
@@ -257,10 +260,8 @@ xfs_attr3_root_inactive(
257260
struct xfs_trans **trans,
258261
struct xfs_inode *dp)
259262
{
260-
struct xfs_mount *mp = dp->i_mount;
261263
struct xfs_da_blkinfo *info;
262264
struct xfs_buf *bp;
263-
xfs_daddr_t blkno;
264265
int error;
265266

266267
/*
@@ -272,7 +273,6 @@ xfs_attr3_root_inactive(
272273
error = xfs_da3_node_read(*trans, dp, 0, &bp, XFS_ATTR_FORK);
273274
if (error)
274275
return error;
275-
blkno = xfs_buf_daddr(bp);
276276

277277
/*
278278
* Invalidate the tree, even if the "tree" is only a single leaf block.
@@ -283,10 +283,26 @@ xfs_attr3_root_inactive(
283283
case cpu_to_be16(XFS_DA_NODE_MAGIC):
284284
case cpu_to_be16(XFS_DA3_NODE_MAGIC):
285285
error = xfs_attr3_node_inactive(trans, dp, bp, 1);
286+
/*
287+
* Empty root node block are not allowed, convert it to leaf.
288+
*/
289+
if (!error)
290+
error = xfs_attr3_leaf_init(*trans, dp, 0);
291+
if (!error)
292+
error = xfs_trans_roll_inode(trans, dp);
286293
break;
287294
case cpu_to_be16(XFS_ATTR_LEAF_MAGIC):
288295
case cpu_to_be16(XFS_ATTR3_LEAF_MAGIC):
289296
error = xfs_attr3_leaf_inactive(trans, dp, bp);
297+
/*
298+
* Reinit the leaf before truncating extents so that a crash
299+
* mid-truncation leaves an empty leaf rather than one with
300+
* entries that may reference freed remote value blocks.
301+
*/
302+
if (!error)
303+
error = xfs_attr3_leaf_init(*trans, dp, 0);
304+
if (!error)
305+
error = xfs_trans_roll_inode(trans, dp);
290306
break;
291307
default:
292308
xfs_dirattr_mark_sick(dp, XFS_ATTR_FORK);
@@ -295,21 +311,6 @@ xfs_attr3_root_inactive(
295311
xfs_trans_brelse(*trans, bp);
296312
break;
297313
}
298-
if (error)
299-
return error;
300-
301-
/*
302-
* Invalidate the incore copy of the root block.
303-
*/
304-
error = xfs_trans_get_buf(*trans, mp->m_ddev_targp, blkno,
305-
XFS_FSB_TO_BB(mp, mp->m_attr_geo->fsbcount), 0, &bp);
306-
if (error)
307-
return error;
308-
xfs_trans_binval(*trans, bp); /* remove from cache */
309-
/*
310-
* Commit the invalidate and start the next transaction.
311-
*/
312-
error = xfs_trans_roll_inode(trans, dp);
313314

314315
return error;
315316
}
@@ -328,6 +329,7 @@ xfs_attr_inactive(
328329
{
329330
struct xfs_trans *trans;
330331
struct xfs_mount *mp;
332+
struct xfs_buf *bp;
331333
int lock_mode = XFS_ILOCK_SHARED;
332334
int error = 0;
333335

@@ -363,10 +365,27 @@ xfs_attr_inactive(
363365
* removal below.
364366
*/
365367
if (dp->i_af.if_nextents > 0) {
368+
/*
369+
* Invalidate and truncate all blocks but leave the root block.
370+
*/
366371
error = xfs_attr3_root_inactive(&trans, dp);
367372
if (error)
368373
goto out_cancel;
369374

375+
error = xfs_itruncate_extents(&trans, dp, XFS_ATTR_FORK,
376+
XFS_FSB_TO_B(mp, mp->m_attr_geo->fsbcount));
377+
if (error)
378+
goto out_cancel;
379+
380+
/*
381+
* Invalidate and truncate the root block and ensure that the
382+
* operation is completed within a single transaction.
383+
*/
384+
error = xfs_da_get_buf(trans, dp, 0, &bp, XFS_ATTR_FORK);
385+
if (error)
386+
goto out_cancel;
387+
388+
xfs_trans_binval(trans, bp);
370389
error = xfs_itruncate_extents(&trans, dp, XFS_ATTR_FORK, 0);
371390
if (error)
372391
goto out_cancel;

0 commit comments

Comments
 (0)